feat(demo): add --kv-cache flag to llm-d pool-metrics demo - #46
feat(demo): add --kv-cache flag to llm-d pool-metrics demo#46jordigilh wants to merge 3 commits into
Conversation
Lets the grid-llmd-pool-metrics-demo drive routing off llm-d's kv-cache-utilization signal instead of the default queue-depth signal, by swapping GridNetwork.spec.scoringPolicy.strategy from queueDepth to kvCachePressure on both sites. Both signals are always shown in the live scorecard; the flag only changes which one drives the A->B flip. - ScoringFlavor enum selects the flavor from the flag and maps it to the strategy YAML value and a pressure-trigger predicate (pressure_phase_active), keyed off the same signal the active scoring strategy actually uses. - materialize_config swaps the strategy anchor on both pool-a-site and pool-b-site when kvCachePressure is selected. - Adds unit tests for the flavor mapping, the pressure predicate, and both materialize_config outcomes (asserted against the same fixture used by the demo's other config-templating tests). Signed-off-by: Jordi Gil <jgil@redhat.com>
Closes the one remaining unit-testable gap identified while auditing this feature's test pyramid: the clap flag itself was previously untested (true for every flag on this Action variant, not just this one). Parses the real Cli/Action tree via Cli::try_parse_from and asserts kv_cache defaults to false and parses to true when passed, so a future clap attribute typo can't silently disconnect the flag from ScoringFlavor::from_kv_cache_flag. With this, every pure/decision-making line this feature added (ScoringFlavor, pressure_phase_active, materialize_config's strategy swap, and now CLI parsing) has 100% unit line coverage (measured with cargo-llvm-cov); only the pre-existing, already-untested imperative-shell dispatch (run(), the env::run match arm) remains uncovered by unit tests, consistent with the rest of this file and validated instead by the live E2E run already recorded in the PR description. Signed-off-by: Jordi Gil <jgil@redhat.com>
|
Ran a follow-up test-pyramid audit on this PR (per project convention: pyramid invariant, behavioral assurance against acceptance criteria, 100% unit coverage of testable logic):
|
|
Ran an independent security review of this diff (the |
…ic fallback Bugbot review of this PR found two related defects in the kvCachePressure path added earlier in this branch: 1. proof_recovery's verification-probe gate was hardcoded to `epp_a.queue_size < 3.0` regardless of scoring flavor. Under kvCachePressure, rank is driven by KV utilization, not queue depth, so pool A could regain rank 0 while queue stayed elevated (or stall below the gate while rank was already 0) -- flaky/false recovery-proof failures in full-mode --kv-cache runs. 2. scrape_epp_metrics read kv_cache from only `inference_pool_average_kv_cache_utilization`, with no fallback to `llm_d_router_epp_average_kv_cache_utilization` -- unlike queue_size, which already falls back symmetrically. An EPP build exposing only the llm_d_router_* series would read kv_cache as a permanent 0.0, so the pressure phase would never announce despite real KV pressure driving the flip. Fixes, via TDD (RED: 5 new tests against not-yet-existing functions -> GREEN: implementation -> REFACTOR: clippy/fmt clean, no duplicated magic numbers): - Extracted scrape_epp_metrics's Prometheus-text parsing into a pure parse_epp_metrics(text: &str) -> EppMetrics function (functional core/imperative shell), and added the missing kv_cache fallback, symmetric with the existing queue_size fallback. - Added recovery_condition_met(flavor, epp), mirroring pressure_phase_active's flavor dispatch: QueueDepth keeps the original threshold (now a named RECOVERY_QUEUE_THRESHOLD constant instead of an inline literal, no behavior change); KvCachePressure reuses the inverse of pressure_phase_active rather than inventing a second, uncalibrated KV constant. - Wired recovery_condition_met into proof_recovery in place of the hardcoded queue check. 100% line coverage of both new functions confirmed with cargo-llvm-cov (all branches of both match statements hit). Full xtask suite: 473 passed, 0 failed (was 468 before this fix). make lint: clippy -D warnings, fmt --check, cargo machete all clean. Signed-off-by: Jordi Gil <jgil@redhat.com>
|
Automated review caught two real defects in the
Fixed via the same TDD discipline as the rest of this PR: 5 new RED tests against not-yet-existing 100% line coverage of both new functions confirmed with |
praxis-bot
left a comment
There was a problem hiding this comment.
Reviewed all three changed files. Clean PR -- no Critical, Large, or Medium issues found.
What looks good:
ScoringFlavorenum is well-designed:from_kv_cache_flag/label/strategy_yamlcleanly separate CLI surface, display, and YAML-template concerns.pressure_phase_activeandrecovery_condition_metcorrectly dispatch on flavor, and the lack of a hysteresis gap for KvCachePressure recovery is explicitly documented as intentional ("reuses the inverse ofpressure_phase_activerather than inventing an untested second KV constant").parse_epp_metricsextraction is a smart refactor -- separating the functional core from the I/O-boundscrape_epp_metricsmakes the metric-name-fallback behavior unit-testable.materialize_configstrategy swap useschecked_replacewithcount=2, which will fail loudly if the template ever changes its number ofscoringPolicy.strategyoccurrences.- 10 new tests cover construction, labels, strategy YAML values, pressure detection for both flavors (including cross-signal independence assertions), metric parsing (primary, fallback, absent), recovery conditions with boundary values, and both materialize_config outcomes. Thorough.
- Existing tests updated to pass the new
scoring_flavorparameter without losing coverage. - README documents both
--kv-cacheand the previously-undocumented--metrics-mtlsflag.
No changes requested.
Summary
Adds a
--kv-cacheflag togrid-llmd-pool-metrics-demothat switches thedemo's routing signal from the default queue-depth scoring strategy to
llm-d's kv-cache-utilization signal, by setting
GridNetwork.spec.scoringPolicy.strategy: kvCachePressureon both sitesinstead of the template's default
queueDepth. This lets the demo showeither of Grid's two real, already-implemented scoring strategies without
touching the operator itself —
ScoringStrategy::KvCachePressureand itsweights are pre-existing, unit-tested operator behavior
(
operator/src/crd/grid_network.rs); this PR only wires the demo's configtemplating and CLI surface to select it.
Both signals (
queue_depthandkv_cache) are always shown in the livescorecard regardless of the flag; only the strategy that actually produces
the
score/rankdriving the A→B failover changes.Design
ScoringFlavorenum (QueueDepthdefault /KvCachePressure) selectedfrom the CLI flag, mapping to the
scoringPolicy.strategyYAML value andto a
pressure_phase_activepredicate that keys the announced "pressure"phase off whichever signal is actually driving the active strategy
(queue size vs. KV utilization), rather than always narrating queue
pressure.
materialize_configswaps thestrategy: queueDepthanchor tostrategy: kvCachePressureon bothpool-a-siteandpool-b-sitewhenthe flavor is selected — same
checked_replace-based templating patternalready used for the mTLS transport transformations in this function.
DemoContext.scoring_flavorthreads the selection through setup and thelive proof-scenario loop; evidence JSON records it as
scoring_strategy: "kv-cache-pressure"/"queue-depth".Testing
predicate for both flavors, and both
materialize_configoutcomes(queue-depth leaves the template's default untouched; kv-cache swaps both
sites, asserted against the same fixture the module's other
config-templating tests already use).
(
strategy: queueDepth, occurring exactly twice) matches the realtests/e2e/topologies/grid-llmd-pool-metrics/forge.yamlbyte-for-byte,not just the synthetic test fixture.
cargo test -p xtask: 466/466 passing.cargo clippy -p xtask --all-targets: clean.rustfmt: clean.--kv-cache --teardown, full mode): environment converged with thekvCachePressurestrategy applied on both sites, and the pressure/flip proof scenario
showed the A→B rank flip driven specifically by the KV-cache signal — the
queue/capacity pressure ratio stayed pegged at
1.00for both poolsthroughout, while
kv_cacherose0.00 → 0.02on pool-a and scoredropped
1.00 → 0.98, flipping rank to pool-b. Recovery drained cleanlyback to pool-a. All 4 proof scenarios (
provenance,baseline,pressure_and_flip,recovery) passed; evidence JSON confirms"scoring_strategy": "kv-cache-pressure","success": true.Docs
Documented the new
--kv-cacheflag (and the existing--metrics-mtlsflag, previously undocumented) in the topology's README.