Skip to content

[LEADS-246] Global cache configuration option#221

Open
xmican10 wants to merge 1 commit intolightspeed-core:mainfrom
xmican10:LEADS-246-single-cache-property
Open

[LEADS-246] Global cache configuration option#221
xmican10 wants to merge 1 commit intolightspeed-core:mainfrom
xmican10:LEADS-246-single-cache-property

Conversation

@xmican10
Copy link
Copy Markdown
Collaborator

@xmican10 xmican10 commented Apr 23, 2026

Description

  • global cache configuration enabled under core system.yaml config
  • override support kept on component level
  • removed embeddings.cache_dir since embeddings and llm queries are cached together

Type of change

  • Refactor
  • New feature
  • Bug fix
  • CVE fix
  • Optimization
  • Documentation Update
  • Configuration Update
  • Bump-up service version
  • Bump-up dependent library
  • Bump-up library or tool used for development (does not change the final image)
  • CI configuration change
  • Unit tests improvement

Tools used to create PR

Identify any AI code assistants used in this PR (for transparency and review context)

  • Assisted-by: (e.g., Claude, CodeRabbit, Ollama, etc., N/A if not used)
  • Generated by: (e.g., tool name and version; N/A if not used)

Related Tickets & Documents

  • Related Issue #
  • Closes #

Checklist before requesting a review

  • I have performed a self-review of my code.
  • PR has passed all pre-merge test jobs.
  • If it is a core feature, I have added thorough tests.

Testing

  • Please provide detailed steps to perform tests related to this code change.
  • How were the fix/results from this change verified? Please provide relevant screenshots or results.

Summary by CodeRabbit

  • New Features

    • Centralized core-level caching with a global enable/disable toggle and unified base directory for all components.
    • Per-component caching can be optionally overridden.
  • Bug Fixes

    • Cache clearing now resolves and deduplicates paths and only clears explicitly configured caches; embedding cache clearing removed when not configured.
  • Tests

    • Updated and added tests to validate global cache propagation and new cache-clearing behavior.

@coderabbitai
Copy link
Copy Markdown
Contributor

coderabbitai Bot commented Apr 23, 2026

Walkthrough

Centralizes caching under core.cache_enabled and core.cache_base_dir; removes per-component hardcoded cache defaults; adds a post-validation global_cache_setup() that derives per-component cache_dir values and updates cache-clearing logic to respect resolved directories.

Changes

Cohort / File(s) Summary
Configuration
config/system.yaml
Adds core.cache_enabled and core.cache_base_dir; removes/commented per-component cache_dir/cache_enabled defaults and shows optional overrides.
Constants
src/lightspeed_evaluation/core/constants.py
Replaces per-component default cache dir constants with DEFAULT_CACHE_BASE_DIR and per-component subdir constants (DEFAULT_*_CACHE_SUBDIR).
Core Models
src/lightspeed_evaluation/core/models/system.py
Adds CoreConfig.cache_enabled and cache_base_dir; makes component cache_dir fields optional; adds SystemConfig.global_cache_setup() validator to compute per-component cache_dir and combine global/component cache_enabled flags; updates LLMPoolConfig.resolve_llm_config to require resolved cache_dir.
Runtime / Runner
src/lightspeed_evaluation/runner/evaluation.py
Updates _clear_caches() to only queue non-empty/resolved cache_dir values, deduplicate paths, and remove embedding cache clearing.
Tests
tests/unit/core/models/test_system.py, tests/unit/runner/test_evaluation.py
Adds TestSystemConfigGlobalCache tests validating propagation, disabling, and override precedence; updates evaluation runner tests to reflect removed embedding cache and optional cache_dir behavior.

Sequence Diagram(s)

sequenceDiagram
    participant User
    participant SystemConfig as SystemConfig (validator)
    participant LLMPool as LLMPool/LLMConfig
    participant Runner as EvaluationRunner
    participant FS as Filesystem
    User->>SystemConfig: provide config (may include core.cache_*)
    SystemConfig->>SystemConfig: global_cache_setup() computes per-component cache_enabled and cache_dir
    SystemConfig->>LLMPool: provide resolved LLM configs (with cache_dir)
    User->>Runner: trigger evaluation
    Runner->>LLMPool: query model configs (cache_dir)
    Runner->>FS: clear/dedupe resolved cache_dir paths
Loading

Estimated code review effort

🎯 4 (Complex) | ⏱️ ~45 minutes

🚥 Pre-merge checks | ✅ 5
✅ Passed checks (5 passed)
Check name Status Explanation
Title check ✅ Passed The title clearly and specifically describes the main change: introducing a global cache configuration option, which is the central objective of the PR.
Docstring Coverage ✅ Passed Docstring coverage is 100.00% which is sufficient. The required threshold is 80.00%.
Linked Issues check ✅ Passed Check skipped because no linked issues were found for this pull request.
Out of Scope Changes check ✅ Passed Check skipped because no linked issues were found for this pull request.
Description Check ✅ Passed Check skipped - CodeRabbit’s high-level summary is enabled.

✏️ Tip: You can configure your own custom pre-merge checks in the settings.

✨ Finishing Touches
🧪 Generate unit tests (beta)
  • Create PR with unit tests

Thanks for using CodeRabbit! It's free for OSS, and your support helps us grow. If you like it, consider giving us a shout-out.

❤️ Share

Comment @coderabbitai help to get the list of available commands and usage tips.

@xmican10 xmican10 marked this pull request as ready for review April 23, 2026 14:33
Copy link
Copy Markdown
Contributor

@coderabbitai coderabbitai Bot left a comment

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Actionable comments posted: 4

🧹 Nitpick comments (2)
tests/unit/core/models/test_system.py (1)

568-710: Missing test case: llm_pool configured without judge_panel.

The new suite thoroughly covers the legacy-llm and judge-panel branches of global_cache_setup(), but there is no test that exercises SystemConfig(llm_pool=LLMPoolConfig(...)) without a judge_panel. That code path is the one where llm_pool.defaults.cache_dir is currently left unset by global_cache_setup() (see the related comment on system.py), and a follow-up call to get_llm_config(...) / resolve_llm_config(...) raises with a confusing message. Adding a test for this combination would have caught that behavior and will regression-guard whichever fix is adopted.

Suggested test sketch:

def test_global_cache_setup_pool_without_panel(self) -> None:
    pool = LLMPoolConfig(
        models={"gpt-4o-mini": LLMProviderConfig(provider="openai")},
    )
    config = SystemConfig(llm_pool=pool)

    assert config.llm_pool is not None
    assert config.llm_pool.defaults.cache_enabled is True
    assert config.llm_pool.defaults.cache_dir == ".caches/llm"
    # Should not raise
    resolved = config.get_llm_config("gpt-4o-mini")
    assert resolved.cache_dir == ".caches/llm/gpt-4o-mini"
🤖 Prompt for AI Agents
Verify each finding against the current code and only fix it if needed.

In `@tests/unit/core/models/test_system.py` around lines 568 - 710, Add a unit
test that constructs a SystemConfig with only llm_pool (LLMPoolConfig with a
models entry like "gpt-4o-mini": LLMProviderConfig(provider="openai")) and no
judge_panel, then assert that config.llm_pool is not None,
config.llm_pool.defaults.cache_enabled is True and
config.llm_pool.defaults.cache_dir == ".caches/llm", and finally call
config.get_llm_config("gpt-4o-mini") (or resolve_llm_config equivalent) and
assert the resolved.cache_dir == ".caches/llm/gpt-4o-mini" to ensure
global_cache_setup populated llm_pool.defaults and that lookups do not raise.
src/lightspeed_evaluation/core/models/system.py (1)

1-1: File-level # pylint: disable=too-many-lines — prefer splitting over suppression.

Repo guidelines state: "Do not disable lint warnings with # noqa, # type: ignore, or # pylint: disable comments - fix the underlying issue instead". This file is now ~1000 lines and the warning is being suppressed rather than addressed. Consider splitting the module by responsibility (e.g. llm.py for LLMConfig/LLMPoolConfig/LLMProviderConfig/LLMParametersConfig/LLMDefaultsConfig, cache.py / core.py for CoreConfig, geval.py for GEvalConfig & rubric, keeping system.py for the orchestrating SystemConfig).

As per coding guidelines: "Do not disable lint warnings with # noqa, # type: ignore, or # pylint: disable comments - fix the underlying issue instead".

🤖 Prompt for AI Agents
Verify each finding against the current code and only fix it if needed.

In `@src/lightspeed_evaluation/core/models/system.py` at line 1, The file-level
suppression "# pylint: disable=too-many-lines" must be removed and the large
module should be split by responsibility: move LLM-related classes (LLMConfig,
LLMPoolConfig, LLMProviderConfig, LLMParametersConfig, LLMDefaultsConfig) into a
new llm.py, move caching/core classes (CoreConfig) into cache.py or core.py,
move GEvalConfig and rubric-related code into geval.py, and keep orchestration
classes (SystemConfig) in system.py; update imports where those classes are
referenced, run tests/linters to ensure no circular imports, and delete the
top-level pylint disable comment once the file is split and each new module is
within size/lint limits.
🤖 Prompt for all review comments with AI agents
Verify each finding against the current code and only fix it if needed.

Inline comments:
In `@config/system.yaml`:
- Around line 29-31: The YAML comment references a non-existent field
core.cache_dir; update the documentation hints to match the actual config field
names defined in CoreConfig by replacing core.cache_dir with
core.cache_base_dir, and likewise replace any api.cache_dir hint with
api.cache_base_dir so the comments match the real configuration fields (refer to
CoreConfig and the api config section when making the changes).

In `@src/lightspeed_evaluation/core/models/system.py`:
- Around line 936-938: The judge_panel + llm_pool branch currently
unconditionally overwrites legacy settings (self.llm.cache_enabled and
self.llm.cache_dir) with llm_pool.defaults, discarding any user-provided values;
change it to honor explicit legacy overrides the same way the non-panel branch
does: set self.llm.cache_dir = self.llm.cache_dir or llm_cache_path (or use the
existing llm_cache_path variable) and only override cache_enabled if
self.llm.cache_enabled is None (or not explicitly set), or alternatively emit a
clear warning via the logger when llm_pool.defaults replaces a non-default
self.llm.cache_dir; update the docstring for judge_panel/llm_pool behavior if
the override is intended.
- Around line 909-955: The global_cache_setup validator only sets
self.llm_pool.defaults.cache_dir when self.judge_panel is present, leaving
llm_pool.defaults.cache_dir None for valid SystemConfig(llm_pool=...) shapes and
causing resolve_llm_config()/get_llm_config() to raise; update
global_cache_setup so that whenever self.llm_pool exists you apply the cache
defaults (set self.llm_pool.defaults.cache_enabled using global_cache_enabled
and ensure self.llm_pool.defaults.cache_dir = self.llm_pool.defaults.cache_dir
or os.path.join(global_cache_base_dir, DEFAULT_LLM_CACHE_SUBDIR)), while
preserving the legacy sync to self.llm when judge_panel is present (keep the
existing branch that copies llm_pool defaults into self.llm for backward
compatibility).

In `@src/lightspeed_evaluation/runner/evaluation.py`:
- Around line 30-42: The code is adding duplicate cache entries when
system_config.llm.cache_dir equals system_config.llm_pool.defaults.cache_dir;
update the logic around cache_dirs in the evaluation runner to de-duplicate by
resolved filesystem path (use pathlib.Path(...).resolve()) so the same directory
isn't added twice: when collecting entries from system_config.llm_pool
(pool.defaults.cache_dir) and system_config.llm.cache_dir, compare resolved
paths and only append if not already present (or build a set of resolved paths
and skip duplicates) while keeping the labels "LLM Judge (pool)" and "LLM Judge"
behavior intact; reference the cache_dirs list, system_config.llm_pool /
LLMPoolConfig, pool.defaults.cache_dir, and system_config.llm.cache_dir to
locate the change.

---

Nitpick comments:
In `@src/lightspeed_evaluation/core/models/system.py`:
- Line 1: The file-level suppression "# pylint: disable=too-many-lines" must be
removed and the large module should be split by responsibility: move LLM-related
classes (LLMConfig, LLMPoolConfig, LLMProviderConfig, LLMParametersConfig,
LLMDefaultsConfig) into a new llm.py, move caching/core classes (CoreConfig)
into cache.py or core.py, move GEvalConfig and rubric-related code into
geval.py, and keep orchestration classes (SystemConfig) in system.py; update
imports where those classes are referenced, run tests/linters to ensure no
circular imports, and delete the top-level pylint disable comment once the file
is split and each new module is within size/lint limits.

In `@tests/unit/core/models/test_system.py`:
- Around line 568-710: Add a unit test that constructs a SystemConfig with only
llm_pool (LLMPoolConfig with a models entry like "gpt-4o-mini":
LLMProviderConfig(provider="openai")) and no judge_panel, then assert that
config.llm_pool is not None, config.llm_pool.defaults.cache_enabled is True and
config.llm_pool.defaults.cache_dir == ".caches/llm", and finally call
config.get_llm_config("gpt-4o-mini") (or resolve_llm_config equivalent) and
assert the resolved.cache_dir == ".caches/llm/gpt-4o-mini" to ensure
global_cache_setup populated llm_pool.defaults and that lookups do not raise.
🪄 Autofix (Beta)

Fix all unresolved CodeRabbit comments on this PR:

  • Push a commit to this branch (recommended)
  • Create a new PR with the fixes

ℹ️ Review info
⚙️ Run configuration

Configuration used: Path: .coderabbit.yaml

Review profile: CHILL

Plan: Pro

Run ID: a11cb9bd-36e9-4f64-a1d1-23021d139da2

📥 Commits

Reviewing files that changed from the base of the PR and between 613addc and 6eb1337.

📒 Files selected for processing (6)
  • config/system.yaml
  • src/lightspeed_evaluation/core/constants.py
  • src/lightspeed_evaluation/core/models/system.py
  • src/lightspeed_evaluation/runner/evaluation.py
  • tests/unit/core/models/test_system.py
  • tests/unit/runner/test_evaluation.py
💤 Files with no reviewable changes (1)
  • tests/unit/runner/test_evaluation.py

Comment thread config/system.yaml Outdated
Comment thread src/lightspeed_evaluation/core/models/system.py
Comment thread src/lightspeed_evaluation/core/models/system.py Outdated
Comment thread src/lightspeed_evaluation/runner/evaluation.py
@xmican10 xmican10 force-pushed the LEADS-246-single-cache-property branch 2 times, most recently from c0d35ce to a6b3df3 Compare April 27, 2026 08:46
Copy link
Copy Markdown
Contributor

@coderabbitai coderabbitai Bot left a comment

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

🧹 Nitpick comments (3)
tests/unit/runner/test_evaluation.py (1)

66-101: Helper still sets up an embedding cache directory that is never exercised.

EmbeddingConfig no longer has a cache_dir field, so _clear_caches cannot — and does not — touch emb_dir or emb.db. The helper still creates both (lines 75, 82), and the docstring claims it covers "pool, API, embedding." This makes the test assertion on line 511 (emb_dir.is_dir()) vacuous and the setup misleading.

Consider dropping emb_dir/emb.db and trimming the docstring, or document explicitly that embedding only contributes a cache_enabled toggle (no directory to clear).

♻️ Suggested cleanup
-    """Dirs + SystemConfig for _clear_caches covering pool, API, embedding.
+    """Dirs + SystemConfig for _clear_caches covering pool and API.
+
+    Embedding has no cache_dir field; its cache is shared with the LLM pool,
+    so only cache_enabled is exercised here.

     Note: When llm_pool is configured, llm.cache_dir is automatically synced
     to llm_pool.defaults.cache_dir by the SystemConfig validator. They share
     the same cache directory.
     """
     pool = tmp_path / "pool_llm"
     api_dir = tmp_path / "api_cache"
-    emb_dir = tmp_path / "emb_cache"
-    for d in (pool, api_dir, emb_dir):
+    for d in (pool, api_dir):
         d.mkdir()
     nested = pool / "nested"
     nested.mkdir()
     (nested / "pool.db").write_text("x")
     (api_dir / "api.db").write_text("x")
-    (emb_dir / "emb.db").write_text("x")

And matching update at lines 501-511 in test_clear_caches_with_all_caches_enabled to drop emb_dir from the directory list and assertion.

🤖 Prompt for AI Agents
Verify each finding against the current code and only fix it if needed.

In `@tests/unit/runner/test_evaluation.py` around lines 66 - 101, Update the
helper _system_config_all_caches_under_tmp to stop creating the unused emb_dir
and emb.db and adjust its docstring to reflect that it only covers pool and API
caches (EmbeddingConfig now only exposes cache_enabled, no cache_dir); remove
the emb_dir and related write_text call, and then update the test
test_clear_caches_with_all_caches_enabled to drop emb_dir from the list of
directories checked/asserted (and any assertions referencing emb_dir or emb.db),
keeping EmbeddingConfig(cache_enabled=True) in the returned SystemConfig so
_clear_caches behavior remains tested for the embedding toggle.
config/system.yaml (1)

29-31: Clarify that cache_dir overrides are absolute paths, not appended to core.cache_base_dir.

The override comments hint that uncommenting overrides core.cache_enabled/core.cache_base_dir, but per global_cache_setup() the override cache_dir is used as-is (self.api.cache_dir or api_cache_path), not joined with the base dir. A user who customizes core.cache_base_dir: /var/caches and then uncomments cache_dir: ".caches/api" will end up with a path unrelated to the configured base. Consider phrasing it as "set an explicit cache directory (replaces the path derived from core.cache_base_dir)".

Also applies to: 96-98

🤖 Prompt for AI Agents
Verify each finding against the current code and only fix it if needed.

In `@config/system.yaml` around lines 29 - 31, Update the comment for the LLM pool
cache override so it clearly states that cache_dir is an explicit absolute path
that replaces the path derived from core.cache_base_dir rather than being
appended to it; reference global_cache_setup() behavior (self.api.cache_dir or
api_cache_path) and mention core.cache_base_dir and cache_dir so readers know
cache_dir overrides the base dir entirely. Apply the same wording change to the
other occurrence around lines 96-98 so both comment blocks consistently explain
that setting cache_dir replaces the derived path.
tests/unit/core/models/test_system.py (1)

568-723: Solid coverage of the new global cache propagation matrix.

Default + legacy override + pool-with-panel + pool-without-panel + global-disabled + per-component override are all exercised, mirroring each branch of SystemConfig.global_cache_setup(). Nice work.

One nit: the comments # Test global_core_setup_propagates global core cache setup (lines 579, 597, 625, 672, 712) reference a non-existent symbol — likely a leftover rename from global_cache_setup. Consider rewording to e.g. # Verify global cache setup propagates to component defaults.

🤖 Prompt for AI Agents
Verify each finding against the current code and only fix it if needed.

In `@tests/unit/core/models/test_system.py` around lines 568 - 723, The comments
in TestSystemConfigGlobalCache refer to a non-existent symbol
`global_core_setup_propagates` (leftover rename), so update those inline
comments in the test methods (e.g.,
test_global_default_cache_setup_legacy_llm_support,
test_global_cache_setup_legacy_llm_support_override,
test_global_default_cache_setup_with_judge_panel,
test_global_cache_turned_off_with_judge_panel,
test_global_cache_setup_with_judge_panel_override) to a clearer phrase such as
"Verify global cache setup propagates to component defaults" (or similar) so
they no longer reference a nonexistent symbol and accurately describe the
behavior of SystemConfig.global_cache_setup.
🤖 Prompt for all review comments with AI agents
Verify each finding against the current code and only fix it if needed.

Nitpick comments:
In `@config/system.yaml`:
- Around line 29-31: Update the comment for the LLM pool cache override so it
clearly states that cache_dir is an explicit absolute path that replaces the
path derived from core.cache_base_dir rather than being appended to it;
reference global_cache_setup() behavior (self.api.cache_dir or api_cache_path)
and mention core.cache_base_dir and cache_dir so readers know cache_dir
overrides the base dir entirely. Apply the same wording change to the other
occurrence around lines 96-98 so both comment blocks consistently explain that
setting cache_dir replaces the derived path.

In `@tests/unit/core/models/test_system.py`:
- Around line 568-723: The comments in TestSystemConfigGlobalCache refer to a
non-existent symbol `global_core_setup_propagates` (leftover rename), so update
those inline comments in the test methods (e.g.,
test_global_default_cache_setup_legacy_llm_support,
test_global_cache_setup_legacy_llm_support_override,
test_global_default_cache_setup_with_judge_panel,
test_global_cache_turned_off_with_judge_panel,
test_global_cache_setup_with_judge_panel_override) to a clearer phrase such as
"Verify global cache setup propagates to component defaults" (or similar) so
they no longer reference a nonexistent symbol and accurately describe the
behavior of SystemConfig.global_cache_setup.

In `@tests/unit/runner/test_evaluation.py`:
- Around line 66-101: Update the helper _system_config_all_caches_under_tmp to
stop creating the unused emb_dir and emb.db and adjust its docstring to reflect
that it only covers pool and API caches (EmbeddingConfig now only exposes
cache_enabled, no cache_dir); remove the emb_dir and related write_text call,
and then update the test test_clear_caches_with_all_caches_enabled to drop
emb_dir from the list of directories checked/asserted (and any assertions
referencing emb_dir or emb.db), keeping EmbeddingConfig(cache_enabled=True) in
the returned SystemConfig so _clear_caches behavior remains tested for the
embedding toggle.

ℹ️ Review info
⚙️ Run configuration

Configuration used: Path: .coderabbit.yaml

Review profile: CHILL

Plan: Pro

Run ID: 76c18a68-9e8b-4a53-8ae0-e4b09d324055

📥 Commits

Reviewing files that changed from the base of the PR and between 6eb1337 and a6b3df3.

📒 Files selected for processing (6)
  • config/system.yaml
  • src/lightspeed_evaluation/core/constants.py
  • src/lightspeed_evaluation/core/models/system.py
  • src/lightspeed_evaluation/runner/evaluation.py
  • tests/unit/core/models/test_system.py
  • tests/unit/runner/test_evaluation.py
✅ Files skipped from review due to trivial changes (1)
  • src/lightspeed_evaluation/core/models/system.py
🚧 Files skipped from review as they are similar to previous changes (1)
  • src/lightspeed_evaluation/runner/evaluation.py

@xmican10 xmican10 force-pushed the LEADS-246-single-cache-property branch from a6b3df3 to 86ab226 Compare April 27, 2026 09:11
Copy link
Copy Markdown
Collaborator

@asamal4 asamal4 left a comment

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Thank you !! LGTM. Few nits..

Also please document the new behavior 1. Deprecation warning, 2. Embedding shares LLM cache.

@@ -1,3 +1,4 @@
# pylint: disable=too-many-lines
Copy link
Copy Markdown
Collaborator

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Hmm.. we will have to split the file/data class

},
)
panel = JudgePanelConfig(judges=["gpt-4o-mini", "gpt-4o"])
embedding = EmbeddingConfig(cache_enabled=True)
Copy link
Copy Markdown
Collaborator

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

We are adding common config for cache at system level, also for now LLM cache is used for embedding..
Why do we need a specific definition for embedding EmbeddingConfig(cache_enabled=True)

Copy link
Copy Markdown
Collaborator Author

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

The embeddings.cache_enabled toggle allows/disallows caching of the embeddings into the LLM cache. Do you want me to remove this?

suffix = cache_suffix if cache_suffix else model_id
if self.defaults.cache_dir is None:
raise ConfigurationError(
"cache_dir must be set by global_cache_setup() before resolving model configs"
Copy link
Copy Markdown
Collaborator

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

is this error message going to help the User ?

Copy link
Copy Markdown
Collaborator Author

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Probably not.. I will remove this

Comment on lines +940 to +941
# LEGACY support
# No llm_pool -> uses legacy llm config only
Copy link
Copy Markdown
Collaborator

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

We should a deprecation warning here

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.

2 participants