ollama-haystack 2.2.0__tar.gz → 2.4.0__tar.gz
This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
- {ollama_haystack-2.2.0 → ollama_haystack-2.4.0}/CHANGELOG.md +14 -0
- {ollama_haystack-2.2.0 → ollama_haystack-2.4.0}/PKG-INFO +4 -2
- {ollama_haystack-2.2.0 → ollama_haystack-2.4.0}/pyproject.toml +4 -8
- {ollama_haystack-2.2.0 → ollama_haystack-2.4.0}/src/haystack_integrations/components/generators/ollama/chat/chat_generator.py +74 -3
- {ollama_haystack-2.2.0 → ollama_haystack-2.4.0}/tests/test_chat_generator.py +102 -4
- {ollama_haystack-2.2.0 → ollama_haystack-2.4.0}/.gitignore +0 -0
- {ollama_haystack-2.2.0 → ollama_haystack-2.4.0}/LICENSE.txt +0 -0
- {ollama_haystack-2.2.0 → ollama_haystack-2.4.0}/README.md +0 -0
- {ollama_haystack-2.2.0 → ollama_haystack-2.4.0}/examples/chat_generator_example.py +0 -0
- {ollama_haystack-2.2.0 → ollama_haystack-2.4.0}/examples/embedders_example.py +0 -0
- {ollama_haystack-2.2.0 → ollama_haystack-2.4.0}/examples/generator_example.py +0 -0
- {ollama_haystack-2.2.0 → ollama_haystack-2.4.0}/pydoc/config.yml +0 -0
- {ollama_haystack-2.2.0 → ollama_haystack-2.4.0}/src/haystack_integrations/components/embedders/ollama/__init__.py +0 -0
- {ollama_haystack-2.2.0 → ollama_haystack-2.4.0}/src/haystack_integrations/components/embedders/ollama/document_embedder.py +0 -0
- {ollama_haystack-2.2.0 → ollama_haystack-2.4.0}/src/haystack_integrations/components/embedders/ollama/text_embedder.py +0 -0
- {ollama_haystack-2.2.0 → ollama_haystack-2.4.0}/src/haystack_integrations/components/generators/ollama/__init__.py +0 -0
- {ollama_haystack-2.2.0 → ollama_haystack-2.4.0}/src/haystack_integrations/components/generators/ollama/chat/__init__.py +0 -0
- {ollama_haystack-2.2.0 → ollama_haystack-2.4.0}/src/haystack_integrations/components/generators/ollama/generator.py +0 -0
- {ollama_haystack-2.2.0 → ollama_haystack-2.4.0}/tests/__init__.py +0 -0
- {ollama_haystack-2.2.0 → ollama_haystack-2.4.0}/tests/test_document_embedder.py +0 -0
- {ollama_haystack-2.2.0 → ollama_haystack-2.4.0}/tests/test_generator.py +0 -0
- {ollama_haystack-2.2.0 → ollama_haystack-2.4.0}/tests/test_text_embedder.py +0 -0
|
@@ -1,5 +1,19 @@
|
|
|
1
1
|
# Changelog
|
|
2
2
|
|
|
3
|
+
## [integrations/ollama-v2.3.0] - 2025-01-29
|
|
4
|
+
|
|
5
|
+
### 🚀 Features
|
|
6
|
+
|
|
7
|
+
- Add `response_format` param to `OllamaChatGenerator` (#1326)
|
|
8
|
+
|
|
9
|
+
|
|
10
|
+
## [integrations/ollama-v2.2.0] - 2025-01-16
|
|
11
|
+
|
|
12
|
+
### 🚀 Features
|
|
13
|
+
|
|
14
|
+
- Ollama - add support for tools (#1294)
|
|
15
|
+
|
|
16
|
+
|
|
3
17
|
## [integrations/ollama-v2.1.2] - 2024-12-18
|
|
4
18
|
|
|
5
19
|
### 🐛 Bug Fixes
|
|
@@ -1,6 +1,6 @@
|
|
|
1
1
|
Metadata-Version: 2.4
|
|
2
2
|
Name: ollama-haystack
|
|
3
|
-
Version: 2.
|
|
3
|
+
Version: 2.4.0
|
|
4
4
|
Summary: An integration between the Ollama LLM framework and Haystack
|
|
5
5
|
Project-URL: Documentation, https://github.com/deepset-ai/haystack-core-integrations/tree/main/integrations/ollama#readme
|
|
6
6
|
Project-URL: Issues, https://github.com/deepset-ai/haystack-core-integrations/issues
|
|
@@ -15,11 +15,13 @@ Classifier: Programming Language :: Python :: 3.9
|
|
|
15
15
|
Classifier: Programming Language :: Python :: 3.10
|
|
16
16
|
Classifier: Programming Language :: Python :: 3.11
|
|
17
17
|
Classifier: Programming Language :: Python :: 3.12
|
|
18
|
+
Classifier: Programming Language :: Python :: 3.13
|
|
18
19
|
Classifier: Programming Language :: Python :: Implementation :: CPython
|
|
19
20
|
Classifier: Programming Language :: Python :: Implementation :: PyPy
|
|
20
|
-
Requires-Python: >=3.
|
|
21
|
+
Requires-Python: >=3.9
|
|
21
22
|
Requires-Dist: haystack-ai
|
|
22
23
|
Requires-Dist: ollama>=0.4.0
|
|
24
|
+
Requires-Dist: pydantic
|
|
23
25
|
Description-Content-Type: text/markdown
|
|
24
26
|
|
|
25
27
|
# ollama-haystack
|
|
@@ -7,7 +7,7 @@ name = "ollama-haystack"
|
|
|
7
7
|
dynamic = ["version"]
|
|
8
8
|
description = 'An integration between the Ollama LLM framework and Haystack'
|
|
9
9
|
readme = "README.md"
|
|
10
|
-
requires-python = ">=3.
|
|
10
|
+
requires-python = ">=3.9"
|
|
11
11
|
license = "Apache-2.0"
|
|
12
12
|
keywords = []
|
|
13
13
|
authors = [
|
|
@@ -23,10 +23,11 @@ classifiers = [
|
|
|
23
23
|
"Programming Language :: Python :: 3.10",
|
|
24
24
|
"Programming Language :: Python :: 3.11",
|
|
25
25
|
"Programming Language :: Python :: 3.12",
|
|
26
|
+
"Programming Language :: Python :: 3.13",
|
|
26
27
|
"Programming Language :: Python :: Implementation :: CPython",
|
|
27
28
|
"Programming Language :: Python :: Implementation :: PyPy",
|
|
28
29
|
]
|
|
29
|
-
dependencies = ["haystack-ai", "ollama>=0.4.0"]
|
|
30
|
+
dependencies = ["haystack-ai", "ollama>=0.4.0", "pydantic"]
|
|
30
31
|
|
|
31
32
|
[project.urls]
|
|
32
33
|
Documentation = "https://github.com/deepset-ai/haystack-core-integrations/tree/main/integrations/ollama#readme"
|
|
@@ -51,7 +52,6 @@ dependencies = [
|
|
|
51
52
|
"pytest",
|
|
52
53
|
"pytest-rerunfailures",
|
|
53
54
|
"haystack-pydoc-tools",
|
|
54
|
-
"jsonschema", # needed for Tool
|
|
55
55
|
]
|
|
56
56
|
[tool.hatch.envs.default.scripts]
|
|
57
57
|
test = "pytest {args:tests}"
|
|
@@ -62,10 +62,6 @@ cov = ["test-cov", "cov-report"]
|
|
|
62
62
|
cov-retry = ["test-cov-retry", "cov-report"]
|
|
63
63
|
docs = ["pydoc-markdown pydoc/config.yml"]
|
|
64
64
|
|
|
65
|
-
[[tool.hatch.envs.all.matrix]]
|
|
66
|
-
python = ["3.9", "3.10", "3.11", "3.12"]
|
|
67
|
-
|
|
68
|
-
|
|
69
65
|
[tool.hatch.envs.lint]
|
|
70
66
|
installer = "uv"
|
|
71
67
|
detached = true
|
|
@@ -165,5 +161,5 @@ markers = [
|
|
|
165
161
|
addopts = ["--import-mode=importlib"]
|
|
166
162
|
|
|
167
163
|
[[tool.mypy.overrides]]
|
|
168
|
-
module = ["haystack.*", "haystack_integrations.*", "pytest.*", "ollama.*"]
|
|
164
|
+
module = ["haystack.*", "haystack_integrations.*", "pytest.*", "ollama.*", "pydantic.*"]
|
|
169
165
|
ignore_missing_imports = true
|
|
@@ -1,9 +1,10 @@
|
|
|
1
|
-
from typing import Any, Callable, Dict, List, Optional, Union
|
|
1
|
+
from typing import Any, Callable, Dict, List, Literal, Optional, Union
|
|
2
2
|
|
|
3
3
|
from haystack import component, default_from_dict, default_to_dict
|
|
4
4
|
from haystack.dataclasses import ChatMessage, StreamingChunk, ToolCall
|
|
5
5
|
from haystack.tools import Tool, _check_duplicate_tool_names, deserialize_tools_inplace
|
|
6
6
|
from haystack.utils.callable_serialization import deserialize_callable, serialize_callable
|
|
7
|
+
from pydantic.json_schema import JsonSchemaValue
|
|
7
8
|
|
|
8
9
|
from ollama import ChatResponse, Client
|
|
9
10
|
|
|
@@ -40,6 +41,60 @@ def _convert_chatmessage_to_ollama_format(message: ChatMessage) -> Dict[str, Any
|
|
|
40
41
|
return ollama_msg
|
|
41
42
|
|
|
42
43
|
|
|
44
|
+
def _convert_ollama_meta_to_openai_format(intput_response_dict: Dict) -> Dict:
|
|
45
|
+
"""
|
|
46
|
+
Internal function to convert Ollama metadata to OpenAI format.
|
|
47
|
+
|
|
48
|
+
All fields that are not part of the OpenAI metadata are left unchanged in the returned dict.
|
|
49
|
+
|
|
50
|
+
Example Ollama metadata:
|
|
51
|
+
{
|
|
52
|
+
'model': 'phi4:14b-q4_K_M',
|
|
53
|
+
'created_at': '2025-03-09T18:38:33.004185821Z',
|
|
54
|
+
'done': True,
|
|
55
|
+
'done_reason': 'stop',
|
|
56
|
+
'total_duration': 86627206961,
|
|
57
|
+
'load_duration': 23585622554,
|
|
58
|
+
'prompt_eval_count': 26,
|
|
59
|
+
'prompt_eval_duration': 3426000000,
|
|
60
|
+
'eval_count': 298,
|
|
61
|
+
'eval_duration': 4799921000
|
|
62
|
+
}
|
|
63
|
+
|
|
64
|
+
Example OpenAI metadata:
|
|
65
|
+
{
|
|
66
|
+
'model': 'phi4:14b-q4_K_M',
|
|
67
|
+
'finish_reason': 'stop',
|
|
68
|
+
'usage': {
|
|
69
|
+
'completion_tokens': 298,
|
|
70
|
+
'prompt_tokens': 26,
|
|
71
|
+
'total_tokens': 324,
|
|
72
|
+
}
|
|
73
|
+
'completion_start_time': '2025-03-09T18:38:33.004185821Z',
|
|
74
|
+
'done': True,
|
|
75
|
+
'total_duration': 86627206961,
|
|
76
|
+
'load_duration': 23585622554,
|
|
77
|
+
'prompt_eval_duration': 3426000000,
|
|
78
|
+
'eval_duration': 4799921000,
|
|
79
|
+
}
|
|
80
|
+
"""
|
|
81
|
+
meta = {key: value for key, value in intput_response_dict.items() if key != "message"}
|
|
82
|
+
|
|
83
|
+
if "done_reason" in meta:
|
|
84
|
+
meta["finish_reason"] = meta.pop("done_reason")
|
|
85
|
+
if "created_at" in meta:
|
|
86
|
+
meta["completion_start_time"] = meta.pop("created_at")
|
|
87
|
+
if "eval_count" in meta and "prompt_eval_count" in meta:
|
|
88
|
+
eval_count = meta.pop("eval_count")
|
|
89
|
+
prompt_eval_count = meta.pop("prompt_eval_count")
|
|
90
|
+
meta["usage"] = {
|
|
91
|
+
"completion_tokens": eval_count,
|
|
92
|
+
"prompt_tokens": prompt_eval_count,
|
|
93
|
+
"total_tokens": eval_count + prompt_eval_count,
|
|
94
|
+
}
|
|
95
|
+
return meta
|
|
96
|
+
|
|
97
|
+
|
|
43
98
|
def _convert_ollama_response_to_chatmessage(ollama_response: "ChatResponse") -> ChatMessage:
|
|
44
99
|
"""
|
|
45
100
|
Converts the non-streaming response from the Ollama API to a ChatMessage with assistant role.
|
|
@@ -59,7 +114,7 @@ def _convert_ollama_response_to_chatmessage(ollama_response: "ChatResponse") ->
|
|
|
59
114
|
|
|
60
115
|
message = ChatMessage.from_assistant(text=text, tool_calls=tool_calls)
|
|
61
116
|
|
|
62
|
-
message.
|
|
117
|
+
message._meta = _convert_ollama_meta_to_openai_format(response_dict)
|
|
63
118
|
return message
|
|
64
119
|
|
|
65
120
|
|
|
@@ -97,6 +152,7 @@ class OllamaChatGenerator:
|
|
|
97
152
|
keep_alive: Optional[Union[float, str]] = None,
|
|
98
153
|
streaming_callback: Optional[Callable[[StreamingChunk], None]] = None,
|
|
99
154
|
tools: Optional[List[Tool]] = None,
|
|
155
|
+
response_format: Optional[Union[None, Literal["json"], JsonSchemaValue]] = None,
|
|
100
156
|
):
|
|
101
157
|
"""
|
|
102
158
|
:param model:
|
|
@@ -124,6 +180,11 @@ class OllamaChatGenerator:
|
|
|
124
180
|
A list of tools for which the model can prepare calls.
|
|
125
181
|
Not all models support tools. For a list of models compatible with tools, see the
|
|
126
182
|
[models page](https://ollama.com/search?c=tools).
|
|
183
|
+
:param response_format:
|
|
184
|
+
The format for structured model outputs. The value can be:
|
|
185
|
+
- None: No specific structure or format is applied to the response. The response is returned as-is.
|
|
186
|
+
- "json": The response is formatted as a JSON object.
|
|
187
|
+
- JSON Schema: The response is formatted as a JSON object that adheres to the specified JSON Schema.
|
|
127
188
|
"""
|
|
128
189
|
|
|
129
190
|
_check_duplicate_tool_names(tools)
|
|
@@ -135,7 +196,7 @@ class OllamaChatGenerator:
|
|
|
135
196
|
self.keep_alive = keep_alive
|
|
136
197
|
self.streaming_callback = streaming_callback
|
|
137
198
|
self.tools = tools
|
|
138
|
-
|
|
199
|
+
self.response_format = response_format
|
|
139
200
|
self._client = Client(host=self.url, timeout=self.timeout)
|
|
140
201
|
|
|
141
202
|
def to_dict(self) -> Dict[str, Any]:
|
|
@@ -156,6 +217,7 @@ class OllamaChatGenerator:
|
|
|
156
217
|
timeout=self.timeout,
|
|
157
218
|
streaming_callback=callback_name,
|
|
158
219
|
tools=serialized_tools,
|
|
220
|
+
response_format=self.response_format,
|
|
159
221
|
)
|
|
160
222
|
|
|
161
223
|
@classmethod
|
|
@@ -237,6 +299,14 @@ class OllamaChatGenerator:
|
|
|
237
299
|
msg = "Ollama does not support tools and streaming at the same time. Please choose one."
|
|
238
300
|
raise ValueError(msg)
|
|
239
301
|
|
|
302
|
+
if self.response_format and tools:
|
|
303
|
+
msg = "Ollama does not support tools and response_format at the same time. Please choose one."
|
|
304
|
+
raise ValueError(msg)
|
|
305
|
+
|
|
306
|
+
if self.response_format and stream:
|
|
307
|
+
msg = "Ollama does not support streaming and response_format at the same time. Please choose one."
|
|
308
|
+
raise ValueError(msg)
|
|
309
|
+
|
|
240
310
|
ollama_tools = [{"type": "function", "function": {**t.tool_spec}} for t in tools] if tools else None
|
|
241
311
|
|
|
242
312
|
ollama_messages = [_convert_chatmessage_to_ollama_format(msg) for msg in messages]
|
|
@@ -247,6 +317,7 @@ class OllamaChatGenerator:
|
|
|
247
317
|
stream=stream,
|
|
248
318
|
keep_alive=self.keep_alive,
|
|
249
319
|
options=generation_kwargs,
|
|
320
|
+
format=self.response_format,
|
|
250
321
|
)
|
|
251
322
|
|
|
252
323
|
if stream:
|
|
@@ -97,13 +97,12 @@ def test_convert_chatmessage_to_ollama_invalid():
|
|
|
97
97
|
|
|
98
98
|
|
|
99
99
|
def test_convert_ollama_response_to_chatmessage():
|
|
100
|
-
model = "some_model"
|
|
101
|
-
|
|
102
100
|
ollama_response = ChatResponse(
|
|
103
|
-
model=
|
|
101
|
+
model="some_model",
|
|
104
102
|
created_at="2023-12-12T14:13:43.416799Z",
|
|
105
103
|
message={"role": "assistant", "content": "Hello! How are you today?"},
|
|
106
104
|
done=True,
|
|
105
|
+
done_reason="stop",
|
|
107
106
|
total_duration=5191566416,
|
|
108
107
|
load_duration=2154458,
|
|
109
108
|
prompt_eval_count=26,
|
|
@@ -117,6 +116,22 @@ def test_convert_ollama_response_to_chatmessage():
|
|
|
117
116
|
assert observed.role == "assistant"
|
|
118
117
|
assert observed.text == "Hello! How are you today?"
|
|
119
118
|
|
|
119
|
+
assert observed.meta == {
|
|
120
|
+
"finish_reason": "stop",
|
|
121
|
+
"usage": {
|
|
122
|
+
"completion_tokens": 298,
|
|
123
|
+
"prompt_tokens": 26,
|
|
124
|
+
"total_tokens": 324,
|
|
125
|
+
},
|
|
126
|
+
"completion_start_time": "2023-12-12T14:13:43.416799Z",
|
|
127
|
+
"load_duration": 2154458,
|
|
128
|
+
"total_duration": 5191566416,
|
|
129
|
+
"eval_duration": 4799921000,
|
|
130
|
+
"prompt_eval_duration": 383809000,
|
|
131
|
+
"done": True,
|
|
132
|
+
"model": "some_model",
|
|
133
|
+
}
|
|
134
|
+
|
|
120
135
|
|
|
121
136
|
def test_convert_ollama_response_to_chatmessage_with_tools():
|
|
122
137
|
model = "some_model"
|
|
@@ -165,6 +180,7 @@ class TestOllamaChatGenerator:
|
|
|
165
180
|
assert component.streaming_callback is None
|
|
166
181
|
assert component.tools is None
|
|
167
182
|
assert component.keep_alive is None
|
|
183
|
+
assert component.response_format is None
|
|
168
184
|
|
|
169
185
|
def test_init(self, tools):
|
|
170
186
|
component = OllamaChatGenerator(
|
|
@@ -175,6 +191,7 @@ class TestOllamaChatGenerator:
|
|
|
175
191
|
keep_alive="10m",
|
|
176
192
|
streaming_callback=print_streaming_chunk,
|
|
177
193
|
tools=tools,
|
|
194
|
+
response_format={"type": "object", "properties": {"name": {"type": "string"}, "age": {"type": "number"}}},
|
|
178
195
|
)
|
|
179
196
|
|
|
180
197
|
assert component.model == "llama2"
|
|
@@ -184,6 +201,10 @@ class TestOllamaChatGenerator:
|
|
|
184
201
|
assert component.keep_alive == "10m"
|
|
185
202
|
assert component.streaming_callback is print_streaming_chunk
|
|
186
203
|
assert component.tools == tools
|
|
204
|
+
assert component.response_format == {
|
|
205
|
+
"type": "object",
|
|
206
|
+
"properties": {"name": {"type": "string"}, "age": {"type": "number"}},
|
|
207
|
+
}
|
|
187
208
|
|
|
188
209
|
def test_init_fail_with_duplicate_tool_names(self, tools):
|
|
189
210
|
|
|
@@ -206,9 +227,11 @@ class TestOllamaChatGenerator:
|
|
|
206
227
|
generation_kwargs={"max_tokens": 10, "some_test_param": "test-params"},
|
|
207
228
|
tools=[tool],
|
|
208
229
|
keep_alive="5m",
|
|
230
|
+
response_format={"type": "object", "properties": {"name": {"type": "string"}, "age": {"type": "number"}}},
|
|
209
231
|
)
|
|
210
232
|
data = component.to_dict()
|
|
211
|
-
|
|
233
|
+
|
|
234
|
+
expected_dict = {
|
|
212
235
|
"type": "haystack_integrations.components.generators.ollama.chat.chat_generator.OllamaChatGenerator",
|
|
213
236
|
"init_parameters": {
|
|
214
237
|
"timeout": 120,
|
|
@@ -235,9 +258,24 @@ class TestOllamaChatGenerator:
|
|
|
235
258
|
},
|
|
236
259
|
},
|
|
237
260
|
],
|
|
261
|
+
"response_format": {
|
|
262
|
+
"type": "object",
|
|
263
|
+
"properties": {"name": {"type": "string"}, "age": {"type": "number"}},
|
|
264
|
+
},
|
|
238
265
|
},
|
|
239
266
|
}
|
|
240
267
|
|
|
268
|
+
# add outputs_to_string, inputs_from_state and outputs_to_state tool parameters for compatibility with
|
|
269
|
+
# haystack-ai>=2.12.0
|
|
270
|
+
if hasattr(tool, "outputs_to_string"):
|
|
271
|
+
expected_dict["init_parameters"]["tools"][0]["data"]["outputs_to_string"] = tool.outputs_to_string
|
|
272
|
+
if hasattr(tool, "inputs_from_state"):
|
|
273
|
+
expected_dict["init_parameters"]["tools"][0]["data"]["inputs_from_state"] = tool.inputs_from_state
|
|
274
|
+
if hasattr(tool, "outputs_to_state"):
|
|
275
|
+
expected_dict["init_parameters"]["tools"][0]["data"]["outputs_to_state"] = tool.outputs_to_state
|
|
276
|
+
|
|
277
|
+
assert data == expected_dict
|
|
278
|
+
|
|
241
279
|
def test_from_dict(self):
|
|
242
280
|
tool = Tool(
|
|
243
281
|
name="name",
|
|
@@ -273,6 +311,10 @@ class TestOllamaChatGenerator:
|
|
|
273
311
|
},
|
|
274
312
|
},
|
|
275
313
|
],
|
|
314
|
+
"response_format": {
|
|
315
|
+
"type": "object",
|
|
316
|
+
"properties": {"name": {"type": "string"}, "age": {"type": "number"}},
|
|
317
|
+
},
|
|
276
318
|
},
|
|
277
319
|
}
|
|
278
320
|
component = OllamaChatGenerator.from_dict(data)
|
|
@@ -286,6 +328,10 @@ class TestOllamaChatGenerator:
|
|
|
286
328
|
}
|
|
287
329
|
assert component.timeout == 120
|
|
288
330
|
assert component.tools == [tool]
|
|
331
|
+
assert component.response_format == {
|
|
332
|
+
"type": "object",
|
|
333
|
+
"properties": {"name": {"type": "string"}, "age": {"type": "number"}},
|
|
334
|
+
}
|
|
289
335
|
|
|
290
336
|
@patch("haystack_integrations.components.generators.ollama.chat.chat_generator.Client")
|
|
291
337
|
def test_run(self, mock_client):
|
|
@@ -319,6 +365,7 @@ class TestOllamaChatGenerator:
|
|
|
319
365
|
tools=None,
|
|
320
366
|
options={},
|
|
321
367
|
keep_alive=None,
|
|
368
|
+
format=None,
|
|
322
369
|
)
|
|
323
370
|
|
|
324
371
|
assert "replies" in result
|
|
@@ -456,3 +503,54 @@ class TestOllamaChatGenerator:
|
|
|
456
503
|
assert isinstance(tool_call, ToolCall)
|
|
457
504
|
assert tool_call.tool_name == "weather"
|
|
458
505
|
assert tool_call.arguments == {"city": "Paris"}
|
|
506
|
+
|
|
507
|
+
@pytest.mark.integration
|
|
508
|
+
def test_run_with_response_format(self):
|
|
509
|
+
response_format = {
|
|
510
|
+
"type": "object",
|
|
511
|
+
"properties": {"capital": {"type": "string"}, "population": {"type": "number"}},
|
|
512
|
+
}
|
|
513
|
+
chat_generator = OllamaChatGenerator(model="llama3.2:3b", response_format=response_format)
|
|
514
|
+
|
|
515
|
+
message = ChatMessage.from_user("What's the capital of France and its population?")
|
|
516
|
+
response = chat_generator.run([message])
|
|
517
|
+
|
|
518
|
+
assert isinstance(response, dict)
|
|
519
|
+
assert isinstance(response["replies"], list)
|
|
520
|
+
|
|
521
|
+
# Parse the response text as JSON and verify its structure
|
|
522
|
+
response_data = json.loads(response["replies"][0].text)
|
|
523
|
+
assert isinstance(response_data, dict)
|
|
524
|
+
assert "capital" in response_data
|
|
525
|
+
assert isinstance(response_data["capital"], str)
|
|
526
|
+
assert "population" in response_data
|
|
527
|
+
assert isinstance(response_data["population"], (int, float))
|
|
528
|
+
assert response_data["capital"] == "Paris"
|
|
529
|
+
|
|
530
|
+
def test_run_with_streaming_and_format(self):
|
|
531
|
+
response_format = {
|
|
532
|
+
"type": "object",
|
|
533
|
+
"properties": {"answer": {"type": "string"}},
|
|
534
|
+
}
|
|
535
|
+
streaming_callback = Mock()
|
|
536
|
+
chat_generator = OllamaChatGenerator(
|
|
537
|
+
model="llama3.2:3b", streaming_callback=streaming_callback, response_format=response_format
|
|
538
|
+
)
|
|
539
|
+
|
|
540
|
+
chat_messages = [
|
|
541
|
+
ChatMessage.from_user("What is the largest city in the United Kingdom by population?"),
|
|
542
|
+
ChatMessage.from_assistant("London is the largest city in the United Kingdom by population"),
|
|
543
|
+
ChatMessage.from_user("And what is the second largest?"),
|
|
544
|
+
]
|
|
545
|
+
with pytest.raises(ValueError):
|
|
546
|
+
chat_generator.run([chat_messages])
|
|
547
|
+
|
|
548
|
+
def test_run_with_tools_and_format(self, tools):
|
|
549
|
+
response_format = {
|
|
550
|
+
"type": "object",
|
|
551
|
+
"properties": {"capital": {"type": "string"}, "population": {"type": "number"}},
|
|
552
|
+
}
|
|
553
|
+
chat_generator = OllamaChatGenerator(model="llama3.2:3b", tools=tools, response_format=response_format)
|
|
554
|
+
message = ChatMessage.from_user("What's the weather in Paris?")
|
|
555
|
+
with pytest.raises(ValueError):
|
|
556
|
+
chat_generator.run([message])
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|