|
13 | 13 | # limitations under the License. |
14 | 14 |
|
15 | 15 |
|
| 16 | +import json |
16 | 17 | from unittest.mock import AsyncMock |
17 | 18 | from unittest.mock import Mock |
18 | 19 |
|
|
38 | 39 | from litellm.types.utils import ModelResponse |
39 | 40 | from litellm.types.utils import StreamingChoices |
40 | 41 | import pytest |
41 | | -import json |
42 | 42 |
|
43 | 43 | LLM_REQUEST_WITH_FUNCTION_DECLARATION = LlmRequest( |
44 | 44 | contents=[ |
@@ -1190,74 +1190,70 @@ async def test_generate_content_async_stream_with_usage_metadata( |
1190 | 1190 | async def test_generate_content_async_multiple_function_calls( |
1191 | 1191 | mock_completion, lite_llm_instance |
1192 | 1192 | ): |
1193 | | - """Test handling of multiple function calls with different indices in streaming mode. |
1194 | | -
|
1195 | | - This test verifies that: |
1196 | | - 1. Multiple function calls with different indices are handled correctly |
1197 | | - 2. Arguments and names are properly accumulated for each function call |
1198 | | - 3. The final response contains all function calls with correct indices |
1199 | | - """ |
1200 | | - mock_completion.return_value = MULTIPLE_FUNCTION_CALLS_STREAM |
1201 | | - |
1202 | | - llm_request = LlmRequest( |
1203 | | - contents=[ |
1204 | | - types.Content( |
1205 | | - role="user", |
1206 | | - parts=[types.Part.from_text(text="Test multiple function calls")], |
1207 | | - ) |
1208 | | - ], |
1209 | | - config=types.GenerateContentConfig( |
1210 | | - tools=[ |
1211 | | - types.Tool( |
1212 | | - function_declarations=[ |
1213 | | - types.FunctionDeclaration( |
1214 | | - name="function_1", |
1215 | | - description="First test function", |
1216 | | - parameters=types.Schema( |
1217 | | - type=types.Type.OBJECT, |
1218 | | - properties={ |
1219 | | - "arg": types.Schema(type=types.Type.STRING), |
1220 | | - }, |
1221 | | - ), |
1222 | | - ), |
1223 | | - types.FunctionDeclaration( |
1224 | | - name="function_2", |
1225 | | - description="Second test function", |
1226 | | - parameters=types.Schema( |
1227 | | - type=types.Type.OBJECT, |
1228 | | - properties={ |
1229 | | - "arg": types.Schema(type=types.Type.STRING), |
1230 | | - }, |
1231 | | - ), |
1232 | | - ), |
1233 | | - ] |
1234 | | - ) |
1235 | | - ], |
1236 | | - ), |
1237 | | - ) |
| 1193 | + """Test handling of multiple function calls with different indices in streaming mode. |
1238 | 1194 |
|
1239 | | - responses = [] |
1240 | | - async for response in lite_llm_instance.generate_content_async( |
1241 | | - llm_request, stream=True |
1242 | | - ): |
1243 | | - responses.append(response) |
1244 | | - |
1245 | | - # Verify we got the final response with both function calls |
1246 | | - assert len(responses) > 0 |
1247 | | - final_response = responses[-1] |
1248 | | - assert final_response.content.role == "model" |
1249 | | - assert len(final_response.content.parts) == 2 |
1250 | | - |
1251 | | - # Verify first function call |
1252 | | - assert final_response.content.parts[0].function_call.name == "function_1" |
1253 | | - assert final_response.content.parts[0].function_call.id == "call_1" |
1254 | | - assert final_response.content.parts[0].function_call.args == { |
1255 | | - "arg": "value1" |
1256 | | - } |
| 1195 | + This test verifies that: |
| 1196 | + 1. Multiple function calls with different indices are handled correctly |
| 1197 | + 2. Arguments and names are properly accumulated for each function call |
| 1198 | + 3. The final response contains all function calls with correct indices |
| 1199 | + """ |
| 1200 | + mock_completion.return_value = MULTIPLE_FUNCTION_CALLS_STREAM |
1257 | 1201 |
|
1258 | | - # Verify second function call |
1259 | | - assert final_response.content.parts[1].function_call.name == "function_2" |
1260 | | - assert final_response.content.parts[1].function_call.id == "call_2" |
1261 | | - assert final_response.content.parts[1].function_call.args == { |
1262 | | - "arg": "value2" |
1263 | | - } |
| 1202 | + llm_request = LlmRequest( |
| 1203 | + contents=[ |
| 1204 | + types.Content( |
| 1205 | + role="user", |
| 1206 | + parts=[types.Part.from_text(text="Test multiple function calls")], |
| 1207 | + ) |
| 1208 | + ], |
| 1209 | + config=types.GenerateContentConfig( |
| 1210 | + tools=[ |
| 1211 | + types.Tool( |
| 1212 | + function_declarations=[ |
| 1213 | + types.FunctionDeclaration( |
| 1214 | + name="function_1", |
| 1215 | + description="First test function", |
| 1216 | + parameters=types.Schema( |
| 1217 | + type=types.Type.OBJECT, |
| 1218 | + properties={ |
| 1219 | + "arg": types.Schema(type=types.Type.STRING), |
| 1220 | + }, |
| 1221 | + ), |
| 1222 | + ), |
| 1223 | + types.FunctionDeclaration( |
| 1224 | + name="function_2", |
| 1225 | + description="Second test function", |
| 1226 | + parameters=types.Schema( |
| 1227 | + type=types.Type.OBJECT, |
| 1228 | + properties={ |
| 1229 | + "arg": types.Schema(type=types.Type.STRING), |
| 1230 | + }, |
| 1231 | + ), |
| 1232 | + ), |
| 1233 | + ] |
| 1234 | + ) |
| 1235 | + ], |
| 1236 | + ), |
| 1237 | + ) |
| 1238 | + |
| 1239 | + responses = [] |
| 1240 | + async for response in lite_llm_instance.generate_content_async( |
| 1241 | + llm_request, stream=True |
| 1242 | + ): |
| 1243 | + responses.append(response) |
| 1244 | + |
| 1245 | + # Verify we got the final response with both function calls |
| 1246 | + assert len(responses) > 0 |
| 1247 | + final_response = responses[-1] |
| 1248 | + assert final_response.content.role == "model" |
| 1249 | + assert len(final_response.content.parts) == 2 |
| 1250 | + |
| 1251 | + # Verify first function call |
| 1252 | + assert final_response.content.parts[0].function_call.name == "function_1" |
| 1253 | + assert final_response.content.parts[0].function_call.id == "call_1" |
| 1254 | + assert final_response.content.parts[0].function_call.args == {"arg": "value1"} |
| 1255 | + |
| 1256 | + # Verify second function call |
| 1257 | + assert final_response.content.parts[1].function_call.name == "function_2" |
| 1258 | + assert final_response.content.parts[1].function_call.id == "call_2" |
| 1259 | + assert final_response.content.parts[1].function_call.args == {"arg": "value2"} |
0 commit comments