@@ -39,10 +39,45 @@ def setUp(self):
3939 ),
4040 }
4141 self .mock_response = ChatCompletion (** self .mock_response )
42+ self .mock_vision_response = {
43+ "id" : "cmpl-4Q8Z5J9Z1Z5z5" ,
44+ "created" : 1635820005 ,
45+ "object" : "chat.completion" ,
46+ "model" : "gpt-4o" ,
47+ "choices" : [
48+ {
49+ "message" : {
50+ "content" : "The image shows a beautiful sunset over mountains." ,
51+ "role" : "assistant" ,
52+ },
53+ "index" : 0 ,
54+ "finish_reason" : "stop" ,
55+ }
56+ ],
57+ "usage" : CompletionUsage (
58+ completion_tokens = 15 , prompt_tokens = 25 , total_tokens = 40
59+ ),
60+ }
61+ self .mock_vision_response = ChatCompletion (** self .mock_vision_response )
4262 self .api_kwargs = {
4363 "messages" : [{"role" : "user" , "content" : "Hello" }],
4464 "model" : "gpt-3.5-turbo" ,
4565 }
66+ self .vision_api_kwargs = {
67+ "messages" : [
68+ {
69+ "role" : "user" ,
70+ "content" : [
71+ {"type" : "text" , "text" : "Describe this image" },
72+ {
73+ "type" : "image_url" ,
74+ "image_url" : {"url" : "https://example.com/image.jpg" , "detail" : "auto" },
75+ },
76+ ],
77+ }
78+ ],
79+ "model" : "gpt-4o" ,
80+ }
4681
4782 def test_encode_image (self ):
4883 # Create a temporary test image file
@@ -93,7 +128,7 @@ def test_prepare_image_content(self):
93128 def test_convert_inputs_to_api_kwargs_with_images (self ):
94129 # Test with single image URL
95130 model_kwargs = {
96- "model" : "gpt-4-vision-preview " ,
131+ "model" : "gpt-4o " ,
97132 "images" : "https://example.com/image.jpg" ,
98133 }
99134 result = self .client .convert_inputs_to_api_kwargs (
@@ -112,7 +147,7 @@ def test_convert_inputs_to_api_kwargs_with_images(self):
112147
113148 # Test with multiple images
114149 model_kwargs = {
115- "model" : "gpt-4-vision-preview " ,
150+ "model" : "gpt-4o " ,
116151 "images" : [
117152 "https://example.com/image1.jpg" ,
118153 "https://example.com/image2.jpg" ,
@@ -199,6 +234,60 @@ def test_call(self, MockSyncOpenAI, mock_init_sync_client):
199234 self .assertEqual (output .usage .prompt_tokens , 20 )
200235 self .assertEqual (output .usage .total_tokens , 30 )
201236
237+ @patch ("adalflow.components.model_client.openai_client.AsyncOpenAI" )
238+ async def test_acall_llm_with_vision (self , MockAsyncOpenAI ):
239+ mock_async_client = AsyncMock ()
240+ MockAsyncOpenAI .return_value = mock_async_client
241+
242+ # Mock the vision model response
243+ mock_async_client .chat .completions .create = AsyncMock (
244+ return_value = self .mock_vision_response
245+ )
246+
247+ # Call the _acall method with vision model
248+ result = await self .client .acall (
249+ api_kwargs = self .vision_api_kwargs , model_type = ModelType .LLM
250+ )
251+
252+ # Assertions
253+ MockAsyncOpenAI .assert_called_once ()
254+ mock_async_client .chat .completions .create .assert_awaited_once_with (
255+ ** self .vision_api_kwargs
256+ )
257+ self .assertEqual (result , self .mock_vision_response )
258+
259+ @patch (
260+ "adalflow.components.model_client.openai_client.OpenAIClient.init_sync_client"
261+ )
262+ @patch ("adalflow.components.model_client.openai_client.OpenAI" )
263+ def test_call_with_vision (self , MockSyncOpenAI , mock_init_sync_client ):
264+ mock_sync_client = Mock ()
265+ MockSyncOpenAI .return_value = mock_sync_client
266+ mock_init_sync_client .return_value = mock_sync_client
267+
268+ # Mock the vision model response
269+ mock_sync_client .chat .completions .create = Mock (return_value = self .mock_vision_response )
270+
271+ # Set the sync client
272+ self .client .sync_client = mock_sync_client
273+
274+ # Call the call method with vision model
275+ result = self .client .call (api_kwargs = self .vision_api_kwargs , model_type = ModelType .LLM )
276+
277+ # Assertions
278+ mock_sync_client .chat .completions .create .assert_called_once_with (
279+ ** self .vision_api_kwargs
280+ )
281+ self .assertEqual (result , self .mock_vision_response )
282+
283+ # Test parse_chat_completion for vision model
284+ output = self .client .parse_chat_completion (completion = self .mock_vision_response )
285+ self .assertTrue (isinstance (output , GeneratorOutput ))
286+ self .assertEqual (output .raw_response , "The image shows a beautiful sunset over mountains." )
287+ self .assertEqual (output .usage .completion_tokens , 15 )
288+ self .assertEqual (output .usage .prompt_tokens , 25 )
289+ self .assertEqual (output .usage .total_tokens , 40 )
290+
202291
203292if __name__ == "__main__" :
204293 unittest .main ()
0 commit comments