mirror of
				https://github.com/amithkoujalgi/ollama4j.git
				synced 2025-11-04 10:30:41 +01:00 
			
		
		
		
	feat: add client-side tool handling option
This commit is contained in:
		@@ -93,6 +93,15 @@ public class OllamaAPI {
 | 
			
		||||
    @SuppressWarnings({"FieldMayBeFinal", "FieldCanBeLocal"})
 | 
			
		||||
    private int numberOfRetriesForModelPull = 0;
 | 
			
		||||
 | 
			
		||||
    /**
 | 
			
		||||
     * When set to true, tools will not be automatically executed by the library.
 | 
			
		||||
     * Instead, tool calls will be returned to the client for manual handling.
 | 
			
		||||
     * <p>
 | 
			
		||||
     * Default is false for backward compatibility.
 | 
			
		||||
     */
 | 
			
		||||
    @Setter
 | 
			
		||||
    private boolean clientHandlesTools = false;
 | 
			
		||||
 | 
			
		||||
    /**
 | 
			
		||||
     * Instantiates the Ollama API with default Ollama host:
 | 
			
		||||
     * <a href="http://localhost:11434">http://localhost:11434</a>
 | 
			
		||||
@@ -1349,6 +1358,10 @@ public class OllamaAPI {
 | 
			
		||||
            result = requestCaller.callSync(request);
 | 
			
		||||
        }
 | 
			
		||||
 | 
			
		||||
        if (clientHandlesTools) {
 | 
			
		||||
            return result;
 | 
			
		||||
        }
 | 
			
		||||
 | 
			
		||||
        // check if toolCallIsWanted
 | 
			
		||||
        List<OllamaChatToolCalls> toolCalls = result.getResponseModel().getMessage().getToolCalls();
 | 
			
		||||
        int toolCallTries = 0;
 | 
			
		||||
 
 | 
			
		||||
@@ -303,6 +303,8 @@ class OllamaAPIIntegrationTest {
 | 
			
		||||
    @Order(11)
 | 
			
		||||
    void testChatWithExplicitToolDefinition() throws OllamaBaseException, IOException, URISyntaxException,
 | 
			
		||||
            InterruptedException, ToolInvocationException {
 | 
			
		||||
        // Ensure default behavior (library handles tools) for baseline assertions
 | 
			
		||||
        api.setClientHandlesTools(false);
 | 
			
		||||
        String theToolModel = TOOLS_MODEL;
 | 
			
		||||
        api.pullModel(theToolModel);
 | 
			
		||||
        OllamaChatRequestBuilder builder = OllamaChatRequestBuilder.getInstance(theToolModel);
 | 
			
		||||
@@ -336,10 +338,61 @@ class OllamaAPIIntegrationTest {
 | 
			
		||||
        assertNull(finalToolCalls, "Final tool calls in the response message should be null");
 | 
			
		||||
    }
 | 
			
		||||
 | 
			
		||||
    @Test
 | 
			
		||||
    @Order(13)
 | 
			
		||||
    void testChatWithExplicitToolDefinitionWithClientHandlesTools() throws OllamaBaseException, IOException, URISyntaxException,
 | 
			
		||||
            InterruptedException, ToolInvocationException {
 | 
			
		||||
        String theToolModel = TOOLS_MODEL;
 | 
			
		||||
        api.pullModel(theToolModel);
 | 
			
		||||
        OllamaChatRequestBuilder builder = OllamaChatRequestBuilder.getInstance(theToolModel);
 | 
			
		||||
 | 
			
		||||
        api.registerTool(employeeFinderTool());
 | 
			
		||||
 | 
			
		||||
        try {
 | 
			
		||||
            // enable client-handled tools so the library does not auto-execute tool calls
 | 
			
		||||
            api.setClientHandlesTools(true);
 | 
			
		||||
 | 
			
		||||
            OllamaChatRequest requestModel = builder
 | 
			
		||||
                    .withMessage(OllamaChatMessageRole.USER, "Give me the ID and address of the employee Rahul Kumar.")
 | 
			
		||||
                    .build();
 | 
			
		||||
            requestModel.setOptions(new OptionsBuilder().setTemperature(0.9f).build().getOptionsMap());
 | 
			
		||||
 | 
			
		||||
            OllamaChatResult chatResult = api.chat(requestModel);
 | 
			
		||||
 | 
			
		||||
            assertNotNull(chatResult, "chatResult should not be null");
 | 
			
		||||
            assertNotNull(chatResult.getResponseModel(), "Response model should not be null");
 | 
			
		||||
            assertNotNull(chatResult.getResponseModel().getMessage(), "Response message should not be null");
 | 
			
		||||
            assertEquals(
 | 
			
		||||
                    OllamaChatMessageRole.ASSISTANT.getRoleName(),
 | 
			
		||||
                    chatResult.getResponseModel().getMessage().getRole().getRoleName(),
 | 
			
		||||
                    "Role of the response message should be ASSISTANT"
 | 
			
		||||
            );
 | 
			
		||||
 | 
			
		||||
            // When clientHandlesTools is true, the assistant message should contain tool calls
 | 
			
		||||
            List<OllamaChatToolCalls> toolCalls = chatResult.getResponseModel().getMessage().getToolCalls();
 | 
			
		||||
            assertNotNull(toolCalls, "Assistant message should contain tool calls when clientHandlesTools is true");
 | 
			
		||||
            assertFalse(toolCalls.isEmpty(), "Tool calls should not be empty");
 | 
			
		||||
            OllamaToolCallsFunction function = toolCalls.get(0).getFunction();
 | 
			
		||||
            assertEquals("get-employee-details", function.getName(), "Tool function name should be 'get-employee-details'");
 | 
			
		||||
            Object employeeName = function.getArguments().get("employee-name");
 | 
			
		||||
            assertNotNull(employeeName, "Employee name argument should not be null");
 | 
			
		||||
            assertEquals("Rahul Kumar", employeeName, "Employee name argument should be 'Rahul Kumar'");
 | 
			
		||||
 | 
			
		||||
            // Since tools were not auto-executed, chat history should contain only the user and assistant messages
 | 
			
		||||
            assertEquals(2, chatResult.getChatHistory().size(),
 | 
			
		||||
                    "Chat history should contain only user and assistant (tool call) messages when clientHandlesTools is true");
 | 
			
		||||
        } finally {
 | 
			
		||||
            // reset to default to avoid affecting other tests
 | 
			
		||||
            api.setClientHandlesTools(false);
 | 
			
		||||
        }
 | 
			
		||||
    }
 | 
			
		||||
 | 
			
		||||
    @Test
 | 
			
		||||
    @Order(14)
 | 
			
		||||
    void testChatWithToolsAndStream() throws OllamaBaseException, IOException, URISyntaxException,
 | 
			
		||||
            InterruptedException, ToolInvocationException {
 | 
			
		||||
        // Ensure default behavior (library handles tools) for streamed test
 | 
			
		||||
        api.setClientHandlesTools(false);
 | 
			
		||||
        String theToolModel = TOOLS_MODEL;
 | 
			
		||||
        api.pullModel(theToolModel);
 | 
			
		||||
 | 
			
		||||
 
 | 
			
		||||
		Reference in New Issue
	
	Block a user