Memoise load_inference_config to skip per-request disk scans

Every passthrough request through `/v1/chat/completions` and the
streaming `/v1/responses` path calls `load_inference_config(model)`
to fold family-default `chat_template_kwargs` (e.g. gpt-oss
`reasoning_effort=medium`) into the outbound body. The function
walks the model_defaults directory recursively via `rglob` inside
`_has_specific_yaml` plus reads two YAML files on every call, so the
hot path was paying the full lookup cost for every token-budget
poll, every tool turn, every reasoning sub-step.

The defaults directory is shipped with the package and does not
mutate at runtime, so wrap both `_has_specific_yaml` and the
expensive inner work of `load_inference_config` in `lru_cache`. The
public entry point still returns a fresh deepcopy of the cached
snapshot so the existing `test_load_returns_a_fresh_dict_per_call`
contract (callers may safely mutate the dict) is preserved.

Adds a regression test pinning the cache-hit count over repeated
calls for the same identifier.
This commit is contained in:
Daniel Han 2026-05-22 15:52:48 +00:00
commit 4577c9c565
2 changed files with 46 additions and 1 deletions

View file

@ -67,6 +67,30 @@ class TestLoadInferenceConfig:
assert cfg["top_p"] == 1.0
assert cfg["top_k"] == 0
def test_repeated_calls_reuse_cached_result(self):
"""The passthrough request path calls ``load_inference_config``
on every chat-completion / Responses request. Cache the heavy
work (YAML reads + recursive ``rglob`` inside
``_has_specific_yaml``) so the hot path doesn't pay the full
scan each time."""
from utils.inference.inference_config import (
_has_specific_yaml,
_load_inference_config_cached,
)
_load_inference_config_cached.cache_clear()
_has_specific_yaml.cache_clear()
ident = "unsloth/gpt-oss-120b-GGUF"
load_inference_config(ident)
load_inference_config(ident)
load_inference_config(ident)
# Three calls, one underlying miss; the rest served from cache.
info = _load_inference_config_cached.cache_info()
assert info.misses == 1, info
assert info.hits >= 2, info
class TestTemperatureBumps:
def test_devstral_temperature_lowered_to_card_value(self):

View file

@ -9,6 +9,8 @@ from model YAML configuration files, with fallback to default.yaml.
Includes family-based lookup from inference_defaults.json for GGUF models.
"""
from copy import deepcopy
from functools import lru_cache
from pathlib import Path
from typing import Dict, Any, Optional
import json
@ -83,8 +85,16 @@ def get_family_inference_params(model_id: str) -> Dict[str, Any]:
return {}
@lru_cache(maxsize = 256)
def _has_specific_yaml(model_identifier: str) -> bool:
"""Check if a model has its own YAML config (not just default.yaml)."""
"""Check if a model has its own YAML config (not just default.yaml).
Cached because the lookup walks ``defaults_dir`` recursively via
``rglob`` on every miss, and every chat-completion / Responses
passthrough request asks the same question for the same loaded
model. The defaults directory is shipped with the package and does
not mutate at runtime, so an LRU cache is safe.
"""
from utils.models.model_config import _REVERSE_MODEL_MAPPING
script_dir = Path(__file__).parent.parent.parent
@ -144,6 +154,17 @@ def load_inference_config(model_identifier: str) -> Dict[str, Any]:
"min_p": float
}
"""
# The heavy work (YAML reads + recursive scan inside
# `_has_specific_yaml`) is memoised on the model identifier; this
# function is called from the hot path of every passthrough
# request. Callers are documented to treat the returned dict as
# immutable, but tests historically mutate it — so deepcopy the
# snapshot before returning to preserve that contract.
return deepcopy(_load_inference_config_cached(model_identifier))
@lru_cache(maxsize = 256)
def _load_inference_config_cached(model_identifier: str) -> Dict[str, Any]:
# Load model defaults to get inference parameters
model_defaults = load_model_defaults(model_identifier)