@@ -165,6 +165,7 @@ def test_init_default(self):
165
165
assert component .streaming_callback is None
166
166
assert component .tools is None
167
167
assert component .keep_alive is None
168
+ assert component .response_format is None
168
169
169
170
def test_init (self , tools ):
170
171
component = OllamaChatGenerator (
@@ -175,6 +176,7 @@ def test_init(self, tools):
175
176
keep_alive = "10m" ,
176
177
streaming_callback = print_streaming_chunk ,
177
178
tools = tools ,
179
+ response_format = {"type" : "object" , "properties" : {"name" : {"type" : "string" }, "age" : {"type" : "number" }}},
178
180
)
179
181
180
182
assert component .model == "llama2"
@@ -184,6 +186,10 @@ def test_init(self, tools):
184
186
assert component .keep_alive == "10m"
185
187
assert component .streaming_callback is print_streaming_chunk
186
188
assert component .tools == tools
189
+ assert component .response_format == {
190
+ "type" : "object" ,
191
+ "properties" : {"name" : {"type" : "string" }, "age" : {"type" : "number" }},
192
+ }
187
193
188
194
def test_init_fail_with_duplicate_tool_names (self , tools ):
189
195
@@ -206,6 +212,7 @@ def test_to_dict(self):
206
212
generation_kwargs = {"max_tokens" : 10 , "some_test_param" : "test-params" },
207
213
tools = [tool ],
208
214
keep_alive = "5m" ,
215
+ response_format = {"type" : "object" , "properties" : {"name" : {"type" : "string" }, "age" : {"type" : "number" }}},
209
216
)
210
217
data = component .to_dict ()
211
218
assert data == {
@@ -235,6 +242,10 @@ def test_to_dict(self):
235
242
},
236
243
},
237
244
],
245
+ "response_format" : {
246
+ "type" : "object" ,
247
+ "properties" : {"name" : {"type" : "string" }, "age" : {"type" : "number" }},
248
+ },
238
249
},
239
250
}
240
251
@@ -273,6 +284,10 @@ def test_from_dict(self):
273
284
},
274
285
},
275
286
],
287
+ "response_format" : {
288
+ "type" : "object" ,
289
+ "properties" : {"name" : {"type" : "string" }, "age" : {"type" : "number" }},
290
+ },
276
291
},
277
292
}
278
293
component = OllamaChatGenerator .from_dict (data )
@@ -286,6 +301,10 @@ def test_from_dict(self):
286
301
}
287
302
assert component .timeout == 120
288
303
assert component .tools == [tool ]
304
+ assert component .response_format == {
305
+ "type" : "object" ,
306
+ "properties" : {"name" : {"type" : "string" }, "age" : {"type" : "number" }},
307
+ }
289
308
290
309
@patch ("haystack_integrations.components.generators.ollama.chat.chat_generator.Client" )
291
310
def test_run (self , mock_client ):
@@ -319,6 +338,7 @@ def test_run(self, mock_client):
319
338
tools = None ,
320
339
options = {},
321
340
keep_alive = None ,
341
+ format = None ,
322
342
)
323
343
324
344
assert "replies" in result
@@ -456,3 +476,54 @@ def test_run_with_tools(self, tools):
456
476
assert isinstance (tool_call , ToolCall )
457
477
assert tool_call .tool_name == "weather"
458
478
assert tool_call .arguments == {"city" : "Paris" }
479
+
480
+ @pytest .mark .integration
481
+ def test_run_with_response_format (self ):
482
+ response_format = {
483
+ "type" : "object" ,
484
+ "properties" : {"capital" : {"type" : "string" }, "population" : {"type" : "number" }},
485
+ }
486
+ chat_generator = OllamaChatGenerator (model = "llama3.2:3b" , response_format = response_format )
487
+
488
+ message = ChatMessage .from_user ("What's the capital of France and its population?" )
489
+ response = chat_generator .run ([message ])
490
+
491
+ assert isinstance (response , dict )
492
+ assert isinstance (response ["replies" ], list )
493
+
494
+ # Parse the response text as JSON and verify its structure
495
+ response_data = json .loads (response ["replies" ][0 ].text )
496
+ assert isinstance (response_data , dict )
497
+ assert "capital" in response_data
498
+ assert isinstance (response_data ["capital" ], str )
499
+ assert "population" in response_data
500
+ assert isinstance (response_data ["population" ], (int , float ))
501
+ assert response_data ["capital" ] == "Paris"
502
+
503
+ def test_run_with_streaming_and_format (self ):
504
+ response_format = {
505
+ "type" : "object" ,
506
+ "properties" : {"answer" : {"type" : "string" }},
507
+ }
508
+ streaming_callback = Mock ()
509
+ chat_generator = OllamaChatGenerator (
510
+ model = "llama3.2:3b" , streaming_callback = streaming_callback , response_format = response_format
511
+ )
512
+
513
+ chat_messages = [
514
+ ChatMessage .from_user ("What is the largest city in the United Kingdom by population?" ),
515
+ ChatMessage .from_assistant ("London is the largest city in the United Kingdom by population" ),
516
+ ChatMessage .from_user ("And what is the second largest?" ),
517
+ ]
518
+ with pytest .raises (ValueError ):
519
+ chat_generator .run ([chat_messages ])
520
+
521
+ def test_run_with_tools_and_format (self , tools ):
522
+ response_format = {
523
+ "type" : "object" ,
524
+ "properties" : {"capital" : {"type" : "string" }, "population" : {"type" : "number" }},
525
+ }
526
+ chat_generator = OllamaChatGenerator (model = "llama3.2:3b" , tools = tools , response_format = response_format )
527
+ message = ChatMessage .from_user ("What's the weather in Paris?" )
528
+ with pytest .raises (ValueError ):
529
+ chat_generator .run ([message ])
0 commit comments