diff --git a/python/packages/autogen-ext/src/autogen_ext/models/cache/_chat_completion_cache.py b/python/packages/autogen-ext/src/autogen_ext/models/cache/_chat_completion_cache.py index 124a3ea7643c..ed263f3f5201 100644 --- a/python/packages/autogen-ext/src/autogen_ext/models/cache/_chat_completion_cache.py +++ b/python/packages/autogen-ext/src/autogen_ext/models/cache/_chat_completion_cache.py @@ -274,14 +274,12 @@ async def create( if cached_result is not None: if isinstance(cached_result, CreateResult): # Cache hit from previous non-streaming call - cached_result.cached = True - return cached_result + return cached_result.model_copy(update={"cached": True}) elif isinstance(cached_result, list): # Cache hit from previous streaming call - extract the final CreateResult for item in reversed(cached_result): if isinstance(item, CreateResult): - item.cached = True - return item + return item.model_copy(update={"cached": True}) # If no CreateResult found in list, fall through to make actual call result = await self.client.create( @@ -325,12 +323,13 @@ async def _generator() -> AsyncGenerator[Union[str, CreateResult], None]: # Cache hit from previous streaming call for result in cached_result: if isinstance(result, CreateResult): - result.cached = True - yield result + yield result.model_copy(update={"cached": True}) + else: + yield result return elif isinstance(cached_result, CreateResult): # Cache hit from previous non-streaming call - convert to streaming format - cached_result.cached = True + cached_result = cached_result.model_copy(update={"cached": True}) # If content is a non-empty string, yield it as a streaming chunk first if isinstance(cached_result.content, str) and cached_result.content: diff --git a/python/packages/autogen-ext/tests/models/test_chat_completion_cache.py b/python/packages/autogen-ext/tests/models/test_chat_completion_cache.py index 8627cb9f6221..dced4f8aa5f8 100644 --- a/python/packages/autogen-ext/tests/models/test_chat_completion_cache.py +++ b/python/packages/autogen-ext/tests/models/test_chat_completion_cache.py @@ -58,6 +58,19 @@ async def test_cache_basic_with_args() -> None: assert response2.content == responses[2] +@pytest.mark.asyncio +async def test_cache_hit_does_not_mutate_original_result() -> None: + _, prompts, system_prompt, _, cached_client = get_test_data(num_messages=1) + messages = [system_prompt, UserMessage(content=prompts[0], source="user")] + + original = await cached_client.create(messages) + cached = await cached_client.create(messages) + + assert not original.cached + assert cached.cached + assert original is not cached + + @pytest.mark.asyncio async def test_cache_structured_output_with_args() -> None: responses, prompts, system_prompt, _, cached_client = get_test_data(num_messages=4)