From 8fa48aba07629e332dd01a0d02c87ac23ad8c632 Mon Sep 17 00:00:00 2001 From: Ryan Stewart Date: Wed, 5 Mar 2025 12:33:22 -0500 Subject: [PATCH 1/5] this allows passing message with 'control' role through python client to enable granite3.2 thinking control functionality --- ollama/_types.py | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/ollama/_types.py b/ollama/_types.py index 710c536e..91626243 100644 --- a/ollama/_types.py +++ b/ollama/_types.py @@ -256,7 +256,7 @@ class Message(SubscriptableBaseModel): Chat message. """ - role: Literal['user', 'assistant', 'system', 'tool'] + role: Literal['user', 'assistant', 'system', 'tool', 'control'] "Assumed role of the message. Response messages has role 'assistant' or 'tool'." content: Optional[str] = None From a704dbf658dbc542a0a9dfe9571452f8daa6aca0 Mon Sep 17 00:00:00 2001 From: rylativity <41017744+rylativity@users.noreply.github.com> Date: Thu, 6 Mar 2025 11:42:32 -0500 Subject: [PATCH 2/5] Update ollama/_types.py to add 'document' to accepted list of roles Co-authored-by: Gabe Goodhart --- ollama/_types.py | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/ollama/_types.py b/ollama/_types.py index 91626243..b9a46625 100644 --- a/ollama/_types.py +++ b/ollama/_types.py @@ -256,7 +256,7 @@ class Message(SubscriptableBaseModel): Chat message. """ - role: Literal['user', 'assistant', 'system', 'tool', 'control'] + role: Literal['user', 'assistant', 'system', 'tool', 'control', 'document'] "Assumed role of the message. Response messages has role 'assistant' or 'tool'." content: Optional[str] = None From f50f553af8b1962e75a661d9cb20b7dc7d18f9f6 Mon Sep 17 00:00:00 2001 From: Ryan Stewart Date: Tue, 18 Mar 2025 20:29:03 -0400 Subject: [PATCH 3/5] this allows passing arbitrary roles in messages --- ollama/_types.py | 2 +- tests/test_client.py | 41 +++++++++++++++++++++++++++++++++++++++-- 2 files changed, 40 insertions(+), 3 deletions(-) diff --git a/ollama/_types.py b/ollama/_types.py index b9a46625..0df0ddbf 100644 --- a/ollama/_types.py +++ b/ollama/_types.py @@ -256,7 +256,7 @@ class Message(SubscriptableBaseModel): Chat message. """ - role: Literal['user', 'assistant', 'system', 'tool', 'control', 'document'] + role: str "Assumed role of the message. Response messages has role 'assistant' or 'tool'." content: Optional[str] = None diff --git a/tests/test_client.py b/tests/test_client.py index 8890afd1..8ccb9db0 100644 --- a/tests/test_client.py +++ b/tests/test_client.py @@ -1,9 +1,11 @@ import base64 +from httpx import Response as httpxResponse import json import os import re -import tempfile from pathlib import Path +import tempfile +from typing import Any, AsyncIterator import pytest from pydantic import BaseModel, ValidationError @@ -11,7 +13,7 @@ from werkzeug.wrappers import Request, Response from ollama._client import CONNECTION_ERROR_MESSAGE, AsyncClient, Client, _copy_tools -from ollama._types import Image +from ollama._types import Image, Message PNG_BASE64 = 'iVBORw0KGgoAAAANSUhEUgAAAAEAAAABCAIAAACQd1PeAAAADElEQVR4nGNgYGAAAAAEAAH2FzhVAAAAAElFTkSuQmCC' PNG_BYTES = base64.b64decode(PNG_BASE64) @@ -1181,3 +1183,38 @@ async def test_async_client_connection_error(): with pytest.raises(ConnectionError) as exc_info: await client.show('model') assert str(exc_info.value) == 'Failed to connect to Ollama. Please check that Ollama is downloaded, running and accessible. https://ollama.com/download' + +def test_arbitrary_roles_accepted_in_message(): + _ = Message(role="somerandomrole", content="I'm ok with you adding any role message now!") + +def _mock_request(*args: Any, **kwargs: Any) -> Response: + return httpxResponse(status_code=200, content="{'response': 'Hello world!'}") + +def test_arbitrary_roles_accepted_in_message_request(monkeypatch:pytest.MonkeyPatch): + + monkeypatch.setattr(Client, "_request", _mock_request) + + client = Client() + + client.chat(model="llama3.1", + messages=[ + {"role":"somerandomrole","content":"I'm ok with you adding any role message now!"}, + {"role":"user","content":"Hello world!"} + ]) + +async def _mock_request_async(*args: Any, **kwargs: Any) -> Response: + return httpxResponse(status_code=200, content="{'response': 'Hello world!'}") + +@pytest.mark.asyncio +async def test_arbitrary_roles_accepted_in_message_request_async(monkeypatch:pytest.MonkeyPatch): + + monkeypatch.setattr(AsyncClient, "_request", _mock_request_async) + + client = AsyncClient() + + await client.chat(model="llama3.1", + messages=[ + {"role":"somerandomrole","content":"I'm ok with you adding any role message now!"}, + {"role":"user","content":"Hello world!"} + ]) + \ No newline at end of file From 40904007dbe94fa5dd39f356e8e14531890fc0ec Mon Sep 17 00:00:00 2001 From: Ryan Stewart Date: Thu, 20 Mar 2025 15:54:06 -0400 Subject: [PATCH 4/5] fix formatting and linting issues in tests/test_client.py --- tests/test_client.py | 6 +++--- 1 file changed, 3 insertions(+), 3 deletions(-) diff --git a/tests/test_client.py b/tests/test_client.py index 8ccb9db0..71f5ba51 100644 --- a/tests/test_client.py +++ b/tests/test_client.py @@ -1,13 +1,13 @@ import base64 -from httpx import Response as httpxResponse import json import os import re -from pathlib import Path import tempfile -from typing import Any, AsyncIterator +from pathlib import Path +from typing import Any import pytest +from httpx import Response as httpxResponse from pydantic import BaseModel, ValidationError from pytest_httpserver import HTTPServer, URIPattern from werkzeug.wrappers import Request, Response From 54ee05caa0da645b3e2a5b0cdc798e3598373db1 Mon Sep 17 00:00:00 2001 From: Ryan Stewart Date: Thu, 20 Mar 2025 15:59:17 -0400 Subject: [PATCH 5/5] format test_client.py --- tests/test_client.py | 34 ++++++++++++++-------------------- 1 file changed, 14 insertions(+), 20 deletions(-) diff --git a/tests/test_client.py b/tests/test_client.py index 71f5ba51..ca29806d 100644 --- a/tests/test_client.py +++ b/tests/test_client.py @@ -1184,37 +1184,31 @@ async def test_async_client_connection_error(): await client.show('model') assert str(exc_info.value) == 'Failed to connect to Ollama. Please check that Ollama is downloaded, running and accessible. https://ollama.com/download' + def test_arbitrary_roles_accepted_in_message(): - _ = Message(role="somerandomrole", content="I'm ok with you adding any role message now!") + _ = Message(role='somerandomrole', content="I'm ok with you adding any role message now!") + def _mock_request(*args: Any, **kwargs: Any) -> Response: - return httpxResponse(status_code=200, content="{'response': 'Hello world!'}") + return httpxResponse(status_code=200, content="{'response': 'Hello world!'}") -def test_arbitrary_roles_accepted_in_message_request(monkeypatch:pytest.MonkeyPatch): - monkeypatch.setattr(Client, "_request", _mock_request) +def test_arbitrary_roles_accepted_in_message_request(monkeypatch: pytest.MonkeyPatch): + monkeypatch.setattr(Client, '_request', _mock_request) client = Client() - client.chat(model="llama3.1", - messages=[ - {"role":"somerandomrole","content":"I'm ok with you adding any role message now!"}, - {"role":"user","content":"Hello world!"} - ]) - + client.chat(model='llama3.1', messages=[{'role': 'somerandomrole', 'content': "I'm ok with you adding any role message now!"}, {'role': 'user', 'content': 'Hello world!'}]) + + async def _mock_request_async(*args: Any, **kwargs: Any) -> Response: - return httpxResponse(status_code=200, content="{'response': 'Hello world!'}") + return httpxResponse(status_code=200, content="{'response': 'Hello world!'}") -@pytest.mark.asyncio -async def test_arbitrary_roles_accepted_in_message_request_async(monkeypatch:pytest.MonkeyPatch): - monkeypatch.setattr(AsyncClient, "_request", _mock_request_async) +@pytest.mark.asyncio +async def test_arbitrary_roles_accepted_in_message_request_async(monkeypatch: pytest.MonkeyPatch): + monkeypatch.setattr(AsyncClient, '_request', _mock_request_async) client = AsyncClient() - await client.chat(model="llama3.1", - messages=[ - {"role":"somerandomrole","content":"I'm ok with you adding any role message now!"}, - {"role":"user","content":"Hello world!"} - ]) - \ No newline at end of file + await client.chat(model='llama3.1', messages=[{'role': 'somerandomrole', 'content': "I'm ok with you adding any role message now!"}, {'role': 'user', 'content': 'Hello world!'}])