From 3d57f4396f0618af1f59bf809c27b0803ac869eb Mon Sep 17 00:00:00 2001 From: Matthias Breddin Date: Fri, 31 Jul 2026 18:13:22 +0200 Subject: [PATCH] Fix: key the AI suggestion cache by model and endpoint (#13449) --------- Co-authored-by: shamoon <4887959+shamoon@users.noreply.github.com> --- src/documents/tests/test_views.py | 36 +++++++++++++++++++++++++++++++ src/documents/views.py | 13 +++++++---- 2 files changed, 45 insertions(+), 4 deletions(-) diff --git a/src/documents/tests/test_views.py b/src/documents/tests/test_views.py index f64b6ea04..0cf1bcdae 100644 --- a/src/documents/tests/test_views.py +++ b/src/documents/tests/test_views.py @@ -491,6 +491,42 @@ class TestAISuggestions(DirectoriesMixin, TestCase): "Titre IA", ) + @patch("documents.views.get_ai_document_classification") + @override_settings( + AI_ENABLED=True, + LLM_BACKEND="mock_backend", + LLM_MODEL="model-a", + LLM_ENDPOINT="http://endpoint-a", + ) + def test_ai_suggestions_cache_key_includes_model_and_endpoint( + self, + mock_get_ai_classification, + ) -> None: + """Cached suggestions are keyed by model and endpoint, so switching + either yields a cache miss instead of a stale hit.""" + mock_get_ai_classification.return_value = { + "title": "Answer A", + "tags": [], + "correspondents": [], + "document_types": [], + "storage_paths": [], + "dates": [], + } + + self.client.force_login(user=self.user) + response = self.client.get( + f"/api/documents/{self.document.pk}/ai_suggestions/", + ) + self.assertEqual(response.status_code, status.HTTP_200_OK) + + # Cached under a key that carries model + endpoint... + self.assertIsNotNone( + get_llm_suggestion_cache( + self.document.pk, + backend="mock_backend:model-a:http://endpoint-a", + ), + ) + @patch("documents.views.get_ai_document_classification") @override_settings( AI_ENABLED=True, diff --git a/src/documents/views.py b/src/documents/views.py index 528d6ced5..3d6018d43 100644 --- a/src/documents/views.py +++ b/src/documents/views.py @@ -1530,10 +1530,15 @@ class DocumentViewSet( return HttpResponseBadRequest("AI is required for this feature") output_language = _get_llm_output_language(ai_config=ai_config, request=request) - llm_cache_backend = ( - f"{ai_config.llm_backend}:{output_language}" - if output_language - else ai_config.llm_backend + llm_cache_backend = ":".join( + part + for part in ( + ai_config.llm_backend, + ai_config.llm_model, + ai_config.llm_endpoint, + output_language, + ) + if part ) cached_llm_suggestions = get_llm_suggestion_cache(