From 75dd13afa10ebd2295ff335546f9f26d007f90bc Mon Sep 17 00:00:00 2001 From: pfolex Date: Sat, 24 Oct 2026 18:39:11 -0400 Subject: [PATCH] types: expose prompt_eval_cached_count in BaseGenerateResponse (#779) - Declare prompt_eval_cached_count: Optional[int] = None on BaseGenerateResponse so it is not dropped by Pydantic during parsing of generate and chat responses. - Add unit tests for GenerateResponse and ChatResponse model serialization and client chat parsing. --- ollama/_types.py | 3 +++ tests/test_client.py | 30 ++++++++++++++++++++++++++++++ tests/test_type_serialization.py | 25 ++++++++++++++++++++++++- 3 files changed, 57 insertions(+), 1 deletion(-) diff --git a/ollama/_types.py b/ollama/_types.py index ad041013..11d946fe 100644 --- a/ollama/_types.py +++ b/ollama/_types.py @@ -249,6 +249,9 @@ class BaseGenerateResponse(SubscriptableBaseModel): prompt_eval_count: Optional[int] = None 'Number of tokens evaluated in the prompt.' + prompt_eval_cached_count: Optional[int] = None + 'Number of prompt tokens served from the prompt cache.' + prompt_eval_duration: Optional[int] = None 'Duration of evaluating the prompt in nanoseconds.' diff --git a/tests/test_client.py b/tests/test_client.py index c212a11d..81ffd7ed 100644 --- a/tests/test_client.py +++ b/tests/test_client.py @@ -62,6 +62,36 @@ def test_client_chat(httpserver: HTTPServer): assert response['message']['content'] == "I don't know." +def test_client_chat_with_prompt_eval_cached_count(httpserver: HTTPServer): + httpserver.expect_ordered_request( + '/api/chat', + method='POST', + json={ + 'model': 'dummy', + 'messages': [{'role': 'user', 'content': 'Hello'}], + 'tools': [], + 'stream': False, + }, + ).respond_with_json( + { + 'model': 'dummy', + 'message': { + 'role': 'assistant', + 'content': 'Hi!', + }, + 'prompt_eval_count': 10, + 'prompt_eval_cached_count': 8, + } + ) + + client = Client(httpserver.url_for('/')) + response = client.chat('dummy', messages=[{'role': 'user', 'content': 'Hello'}]) + assert response['prompt_eval_count'] == 10 + assert response['prompt_eval_cached_count'] == 8 + assert response.prompt_eval_cached_count == 8 + + + def test_client_chat_with_logprobs(httpserver: HTTPServer): httpserver.expect_ordered_request( '/api/chat', diff --git a/tests/test_type_serialization.py b/tests/test_type_serialization.py index e1af3512..4b27dbd1 100644 --- a/tests/test_type_serialization.py +++ b/tests/test_type_serialization.py @@ -4,7 +4,7 @@ import pytest -from ollama._types import ChatRequest, CreateRequest, GenerateRequest, Image +from ollama._types import ChatRequest, ChatResponse, CreateRequest, GenerateRequest, GenerateResponse, Image def test_image_serialization_bytes(): @@ -122,3 +122,26 @@ def test_think_boolean_serialization(): assert ChatRequest(model='test-model', think=True).model_dump(exclude_none=True)['think'] is True assert ChatRequest(model='test-model', think=False).model_dump(exclude_none=True)['think'] is False assert 'think' not in ChatRequest(model='test-model', think=None).model_dump(exclude_none=True) + + +def test_response_prompt_eval_cached_count(): + gen_resp = GenerateResponse(model='test-model', prompt_eval_count=100, prompt_eval_cached_count=80) + assert gen_resp.prompt_eval_cached_count == 80 + assert gen_resp['prompt_eval_cached_count'] == 80 + assert gen_resp.model_dump(exclude_none=True)['prompt_eval_cached_count'] == 80 + + chat_resp = ChatResponse( + model='test-model', + message={'role': 'assistant', 'content': 'hi'}, + prompt_eval_count=100, + prompt_eval_cached_count=80, + ) + assert chat_resp.prompt_eval_cached_count == 80 + assert chat_resp['prompt_eval_cached_count'] == 80 + assert chat_resp.model_dump(exclude_none=True)['prompt_eval_cached_count'] == 80 + + default_resp = GenerateResponse(model='test-model') + assert default_resp.prompt_eval_cached_count is None + assert 'prompt_eval_cached_count' not in default_resp + assert 'prompt_eval_cached_count' not in default_resp.model_dump(exclude_none=True) +