fix(ml): preloaded model loaded twice (#32610)
fix(ml): reuse cached model across names that clean to the same model (cherry picked from commit 166e93559f123313cf9cb4e7324c4ee30e21c618)
This commit is contained in:
@@ -3,6 +3,7 @@ from collections.abc import Hashable
|
||||
from typing import Any
|
||||
|
||||
from immich_ml import allocator
|
||||
from immich_ml.config import clean_name
|
||||
from immich_ml.models.base import InferenceEntry, InferenceModel
|
||||
from immich_ml.schemas import Options
|
||||
|
||||
@@ -15,7 +16,8 @@ class ModelCache:
|
||||
self._expiries: dict[Key, asyncio.TimerHandle] = {}
|
||||
|
||||
def get[O: Options](self, entry: InferenceEntry[O], ttl: int | None = None) -> InferenceModel[O]:
|
||||
key = (entry.model, entry.name, entry.model.graph(entry.options))
|
||||
# names that differ only in what cleaning drops, like an `immich-app/` prefix, are the same model
|
||||
key = (entry.model, clean_name(entry.name), entry.model.graph(entry.options))
|
||||
if key not in self._models:
|
||||
self._models[key] = entry.model.create(entry.name, entry.options)
|
||||
elif key not in self._expiries:
|
||||
|
||||
@@ -1856,6 +1856,14 @@ class TestCache:
|
||||
assert len(model_cache._models) == 1
|
||||
model.create.assert_called_once()
|
||||
|
||||
async def test_shares_an_instance_across_names_of_the_same_model(self) -> None:
|
||||
model_cache = ModelCache()
|
||||
bare = model_cache.get(InferenceEntry(OpenClipTextualEncoder, "ViT-B-32__openai", TextualOptions()))
|
||||
prefixed = model_cache.get(
|
||||
InferenceEntry(OpenClipTextualEncoder, "immich-app/ViT-B-32__openai", TextualOptions(language="en-US"))
|
||||
)
|
||||
assert bare is prefixed
|
||||
|
||||
async def test_separate_instances_per_graph_option(self) -> None:
|
||||
# the real TextDetector, so that keying it on anything but its resolution fails this
|
||||
model_cache = ModelCache()
|
||||
|
||||
Reference in New Issue
Block a user