mirror of
https://github.com/amithkoujalgi/ollama4j.git
synced 2025-10-13 17:08:57 +02:00
Refactor OllamaAPI exception handling to properly manage InterruptedException and improve logging. Remove unused Logback Classic dependency from pom.xml and clean up commented-out code in integration tests.
This commit is contained in:
parent
e9a4599714
commit
36f7d14c68
8
pom.xml
8
pom.xml
@ -276,14 +276,6 @@
|
||||
<version>2.0.17</version>
|
||||
</dependency>
|
||||
|
||||
<!-- <!– Logger impl - Logback Classic (SLF4J binding) - Disabled on JAR build –>-->
|
||||
<!-- <dependency>-->
|
||||
<!-- <groupId>ch.qos.logback</groupId>-->
|
||||
<!-- <artifactId>logback-classic</artifactId>-->
|
||||
<!-- <version>1.4.12</version>-->
|
||||
<!-- <scope>test</scope>-->
|
||||
<!-- </dependency>-->
|
||||
|
||||
<dependency>
|
||||
<groupId>org.junit.jupiter</groupId>
|
||||
<artifactId>junit-jupiter-api</artifactId>
|
||||
|
@ -109,7 +109,6 @@ public class OllamaAPI {
|
||||
*/
|
||||
public OllamaAPI() {
|
||||
this.host = "http://localhost:11434";
|
||||
// initializeMetrics();
|
||||
}
|
||||
|
||||
/**
|
||||
@ -124,7 +123,6 @@ public class OllamaAPI {
|
||||
this.host = host;
|
||||
}
|
||||
LOG.info("Ollama4j client initialized. Connected to Ollama server at: {}", this.host);
|
||||
// initializeMetrics();
|
||||
}
|
||||
|
||||
/**
|
||||
@ -174,6 +172,9 @@ public class OllamaAPI {
|
||||
response = httpClient.send(httpRequest, HttpResponse.BodyHandlers.ofString());
|
||||
statusCode = response.statusCode();
|
||||
return statusCode == 200;
|
||||
} catch (InterruptedException ie) {
|
||||
Thread.currentThread().interrupt();
|
||||
throw new OllamaException("Ping interrupted", ie);
|
||||
} catch (Exception e) {
|
||||
throw new OllamaException("Ping failed", e);
|
||||
} finally {
|
||||
@ -220,6 +221,9 @@ public class OllamaAPI {
|
||||
} else {
|
||||
throw new OllamaException(statusCode + " - " + responseString);
|
||||
}
|
||||
} catch (InterruptedException ie) {
|
||||
Thread.currentThread().interrupt();
|
||||
throw new OllamaException("ps interrupted", ie);
|
||||
} catch (Exception e) {
|
||||
throw new OllamaException("ps failed", e);
|
||||
} finally {
|
||||
@ -262,6 +266,9 @@ public class OllamaAPI {
|
||||
} else {
|
||||
throw new OllamaException(statusCode + " - " + responseString);
|
||||
}
|
||||
} catch (InterruptedException ie) {
|
||||
Thread.currentThread().interrupt();
|
||||
throw new OllamaException("listModels interrupted", ie);
|
||||
} catch (Exception e) {
|
||||
throw new OllamaException(e.getMessage(), e);
|
||||
} finally {
|
||||
@ -353,6 +360,9 @@ public class OllamaAPI {
|
||||
if (statusCode != 200) {
|
||||
throw new OllamaException(statusCode + " - " + responseString);
|
||||
}
|
||||
} catch (InterruptedException ie) {
|
||||
Thread.currentThread().interrupt();
|
||||
throw new OllamaException("Thread was interrupted during model pull.", ie);
|
||||
} catch (Exception e) {
|
||||
throw new OllamaException(e.getMessage(), e);
|
||||
} finally {
|
||||
@ -425,6 +435,9 @@ public class OllamaAPI {
|
||||
} else {
|
||||
throw new OllamaException(statusCode + " - " + responseString);
|
||||
}
|
||||
} catch (InterruptedException ie) {
|
||||
Thread.currentThread().interrupt();
|
||||
throw new OllamaException("Thread was interrupted", ie);
|
||||
} catch (Exception e) {
|
||||
throw new OllamaException(e.getMessage(), e);
|
||||
} finally {
|
||||
@ -468,6 +481,9 @@ public class OllamaAPI {
|
||||
+ " after "
|
||||
+ numberOfRetriesForModelPull
|
||||
+ " retries");
|
||||
} catch (InterruptedException ie) {
|
||||
Thread.currentThread().interrupt();
|
||||
throw new OllamaException("Thread was interrupted", ie);
|
||||
} catch (Exception e) {
|
||||
throw new OllamaException(e.getMessage(), e);
|
||||
}
|
||||
@ -507,6 +523,9 @@ public class OllamaAPI {
|
||||
} else {
|
||||
throw new OllamaException(statusCode + " - " + responseBody);
|
||||
}
|
||||
} catch (InterruptedException ie) {
|
||||
Thread.currentThread().interrupt();
|
||||
throw new OllamaException("Thread was interrupted", ie);
|
||||
} catch (Exception e) {
|
||||
throw new OllamaException(e.getMessage(), e);
|
||||
} finally {
|
||||
@ -555,7 +574,7 @@ public class OllamaAPI {
|
||||
new BufferedReader(
|
||||
new InputStreamReader(response.body(), StandardCharsets.UTF_8))) {
|
||||
String line;
|
||||
StringBuffer lines = new StringBuffer();
|
||||
StringBuilder lines = new StringBuilder();
|
||||
while ((line = reader.readLine()) != null) {
|
||||
ModelPullResponse res =
|
||||
Utils.getObjectMapper().readValue(line, ModelPullResponse.class);
|
||||
@ -568,6 +587,9 @@ public class OllamaAPI {
|
||||
}
|
||||
out = lines;
|
||||
}
|
||||
} catch (InterruptedException e) {
|
||||
Thread.currentThread().interrupt();
|
||||
throw new OllamaException("Thread was interrupted", e);
|
||||
} catch (Exception e) {
|
||||
throw new OllamaException(e.getMessage(), e);
|
||||
} finally {
|
||||
@ -617,6 +639,9 @@ public class OllamaAPI {
|
||||
if (statusCode != 200) {
|
||||
throw new OllamaException(statusCode + " - " + responseBody);
|
||||
}
|
||||
} catch (InterruptedException e) {
|
||||
Thread.currentThread().interrupt();
|
||||
throw new OllamaException("Thread was interrupted", e);
|
||||
} catch (Exception e) {
|
||||
throw new OllamaException(statusCode + " - " + out, e);
|
||||
} finally {
|
||||
@ -674,6 +699,10 @@ public class OllamaAPI {
|
||||
LOG.debug("Unload response: {} - {}", statusCode, responseBody);
|
||||
throw new OllamaException(statusCode + " - " + responseBody);
|
||||
}
|
||||
} catch (InterruptedException e) {
|
||||
Thread.currentThread().interrupt();
|
||||
LOG.debug("Unload interrupted: {} - {}", statusCode, out);
|
||||
throw new OllamaException(statusCode + " - " + out, e);
|
||||
} catch (Exception e) {
|
||||
LOG.debug("Unload failed: {} - {}", statusCode, out);
|
||||
throw new OllamaException(statusCode + " - " + out, e);
|
||||
@ -716,6 +745,9 @@ public class OllamaAPI {
|
||||
} else {
|
||||
throw new OllamaException(statusCode + " - " + responseBody);
|
||||
}
|
||||
} catch (InterruptedException e) {
|
||||
Thread.currentThread().interrupt();
|
||||
throw new OllamaException("Thread was interrupted", e);
|
||||
} catch (Exception e) {
|
||||
throw new OllamaException(e.getMessage(), e);
|
||||
} finally {
|
||||
@ -848,7 +880,6 @@ public class OllamaAPI {
|
||||
if (request.isUseTools()) {
|
||||
// add all registered tools to request
|
||||
request.setTools(toolRegistry.getRegisteredTools());
|
||||
System.out.println("Use tools is set.");
|
||||
}
|
||||
|
||||
if (tokenHandler != null) {
|
||||
@ -907,6 +938,9 @@ public class OllamaAPI {
|
||||
toolCallTries++;
|
||||
}
|
||||
return result;
|
||||
} catch (InterruptedException e) {
|
||||
Thread.currentThread().interrupt();
|
||||
throw new OllamaException("Thread was interrupted", e);
|
||||
} catch (Exception e) {
|
||||
throw new OllamaException(e.getMessage(), e);
|
||||
}
|
||||
@ -1124,6 +1158,9 @@ public class OllamaAPI {
|
||||
statusCode = result.getHttpStatusCode();
|
||||
out = result;
|
||||
return result;
|
||||
} catch (InterruptedException e) {
|
||||
Thread.currentThread().interrupt();
|
||||
throw new OllamaException("Thread was interrupted", e);
|
||||
} catch (Exception e) {
|
||||
throw new OllamaException(e.getMessage(), e);
|
||||
} finally {
|
||||
|
@ -136,19 +136,25 @@ public class OllamaAsyncResultStreamer extends Thread {
|
||||
try {
|
||||
reader.close();
|
||||
} catch (IOException e) {
|
||||
/* do nothing */
|
||||
}
|
||||
}
|
||||
if (responseBodyStream != null) {
|
||||
try {
|
||||
responseBodyStream.close();
|
||||
} catch (IOException e) {
|
||||
/* do nothing */
|
||||
}
|
||||
}
|
||||
}
|
||||
if (statusCode != 200) {
|
||||
throw new OllamaException(this.completeResponse);
|
||||
}
|
||||
} catch (IOException | InterruptedException | OllamaException e) {
|
||||
} catch (InterruptedException e) {
|
||||
Thread.currentThread().interrupt();
|
||||
this.succeeded = false;
|
||||
this.completeResponse = "[FAILED] " + e.getMessage();
|
||||
} catch (IOException | OllamaException e) {
|
||||
this.succeeded = false;
|
||||
this.completeResponse = "[FAILED] " + e.getMessage();
|
||||
}
|
||||
|
@ -336,7 +336,6 @@ class OllamaAPIIntegrationTest {
|
||||
.withThink(false)
|
||||
.withOptions(new OptionsBuilder().build())
|
||||
.build();
|
||||
OllamaGenerateStreamObserver handler = null;
|
||||
OllamaResult result =
|
||||
api.generate(
|
||||
request,
|
||||
@ -821,33 +820,6 @@ class OllamaAPIIntegrationTest {
|
||||
assertNotNull(chatResult.getResponseModel());
|
||||
}
|
||||
|
||||
// /**
|
||||
// * Tests generateWithImages using an image URL as input.
|
||||
// *
|
||||
// * <p>Scenario: Calls generateWithImages with a vision model and an image URL,expecting a
|
||||
// * non-empty response. Usage: generateWithImages, image from URL, no streaming.
|
||||
// */
|
||||
// @Test
|
||||
// @Order(17)
|
||||
// void shouldGenerateWithImageURLs()
|
||||
// throws OllamaBaseException {
|
||||
// api.pullModel(VISION_MODEL);
|
||||
//
|
||||
// OllamaResult result =
|
||||
// api.generateWithImages(
|
||||
// VISION_MODEL,
|
||||
// "What is in this image?",
|
||||
// List.of(
|
||||
//
|
||||
// "https://i.pinimg.com/736x/f9/4e/cb/f94ecba040696a3a20b484d2e15159ec.jpg"),
|
||||
// new OptionsBuilder().build(),
|
||||
// null,
|
||||
// null);
|
||||
// assertNotNull(result);
|
||||
// assertNotNull(result.getResponse());
|
||||
// assertFalse(result.getResponse().isEmpty());
|
||||
// }
|
||||
|
||||
/**
|
||||
* Tests generateWithImages using an image file as input.
|
||||
*
|
||||
@ -1041,38 +1013,6 @@ class OllamaAPIIntegrationTest {
|
||||
assertFalse(result.getResponse().isEmpty());
|
||||
}
|
||||
|
||||
// /**
|
||||
// * Tests generate with raw=true and thinking enabled.
|
||||
// *
|
||||
// * <p>Scenario: Calls generate with raw=true and think=true combination. Usage: generate,
|
||||
// * raw=true, thinking enabled, no streaming.
|
||||
// */
|
||||
// @Test
|
||||
// @Order(23)
|
||||
// void shouldGenerateWithRawModeAndThinking()
|
||||
// throws OllamaBaseException
|
||||
// {
|
||||
// api.pullModel(THINKING_TOOL_MODEL_2);
|
||||
// api.unloadModel(THINKING_TOOL_MODEL_2);
|
||||
// boolean raw =
|
||||
// true; // if true no formatting will be applied to the prompt. You may choose
|
||||
// to use
|
||||
// // the raw parameter if you are specifying a full templated prompt in your
|
||||
// // request to the API
|
||||
// boolean thinking = true;
|
||||
// OllamaResult result =
|
||||
// api.generate(
|
||||
// THINKING_TOOL_MODEL_2,
|
||||
// "Validate: 1+1=2",
|
||||
// raw,
|
||||
// thinking,
|
||||
// new OptionsBuilder().build(),
|
||||
// new OllamaGenerateStreamObserver(null, null));
|
||||
// assertNotNull(result);
|
||||
// assertNotNull(result.getResponse());
|
||||
// assertNotNull(result.getThinking());
|
||||
// }
|
||||
|
||||
/**
|
||||
* Tests generate with all parameters enabled: raw=true, thinking=true, and streaming.
|
||||
*
|
||||
|
@ -90,20 +90,6 @@ class TestMockedAPIs {
|
||||
}
|
||||
}
|
||||
|
||||
// @Test
|
||||
// void testRegisteredTools() {
|
||||
// OllamaAPI ollamaAPI = Mockito.mock(OllamaAPI.class);
|
||||
// doNothing().when(ollamaAPI).registerTools(Collections.emptyList());
|
||||
// ollamaAPI.registerTools(Collections.emptyList());
|
||||
// verify(ollamaAPI, times(1)).registerTools(Collections.emptyList());
|
||||
//
|
||||
// List<Tools.ToolSpecification> toolSpecifications = new ArrayList<>();
|
||||
// toolSpecifications.add(getSampleToolSpecification());
|
||||
// doNothing().when(ollamaAPI).registerTools(toolSpecifications);
|
||||
// ollamaAPI.registerTools(toolSpecifications);
|
||||
// verify(ollamaAPI, times(1)).registerTools(toolSpecifications);
|
||||
// }
|
||||
|
||||
@Test
|
||||
void testGetModelDetails() {
|
||||
OllamaAPI ollamaAPI = Mockito.mock(OllamaAPI.class);
|
||||
@ -169,7 +155,6 @@ class TestMockedAPIs {
|
||||
OllamaAPI ollamaAPI = Mockito.mock(OllamaAPI.class);
|
||||
String model = "llama2";
|
||||
String prompt = "some prompt text";
|
||||
OptionsBuilder optionsBuilder = new OptionsBuilder();
|
||||
OllamaGenerateStreamObserver observer = new OllamaGenerateStreamObserver(null, null);
|
||||
try {
|
||||
OllamaGenerateRequest request =
|
||||
@ -318,64 +303,4 @@ class TestMockedAPIs {
|
||||
throw new RuntimeException("Failed to run test: testGetRoleFound");
|
||||
}
|
||||
}
|
||||
|
||||
// private static Tools.ToolSpecification getSampleToolSpecification() {
|
||||
// return Tools.ToolSpecification.builder()
|
||||
// .functionName("current-weather")
|
||||
// .functionDescription("Get current weather")
|
||||
// .toolFunction(
|
||||
// new ToolFunction() {
|
||||
// @Override
|
||||
// public Object apply(Map<String, Object> arguments) {
|
||||
// String location = arguments.get("city").toString();
|
||||
// return "Currently " + location + "'s weather is beautiful.";
|
||||
// }
|
||||
// })
|
||||
// .toolPrompt(
|
||||
// Tools.PromptFuncDefinition.builder()
|
||||
// .type("prompt")
|
||||
// .function(
|
||||
// Tools.PromptFuncDefinition.PromptFuncSpec.builder()
|
||||
// .name("get-location-weather-info")
|
||||
// .description("Get location details")
|
||||
// .parameters(
|
||||
// Tools.PromptFuncDefinition.Parameters
|
||||
// .builder()
|
||||
// .type("object")
|
||||
// .properties(
|
||||
// Map.of(
|
||||
// "city",
|
||||
// Tools
|
||||
//
|
||||
// .PromptFuncDefinition
|
||||
//
|
||||
// .Property
|
||||
//
|
||||
// .builder()
|
||||
// .type(
|
||||
//
|
||||
// "string")
|
||||
//
|
||||
// .description(
|
||||
//
|
||||
// "The city,"
|
||||
//
|
||||
// + " e.g."
|
||||
//
|
||||
// + " New Delhi,"
|
||||
//
|
||||
// + " India")
|
||||
//
|
||||
// .required(
|
||||
//
|
||||
// true)
|
||||
//
|
||||
// .build()))
|
||||
//
|
||||
// .required(java.util.List.of("city"))
|
||||
// .build())
|
||||
// .build())
|
||||
// .build())
|
||||
// .build();
|
||||
// }
|
||||
}
|
||||
|
@ -37,29 +37,4 @@ class TestOllamaChatRequestBuilder {
|
||||
assertNotNull(afterReset.getMessages());
|
||||
assertEquals(0, afterReset.getMessages().size());
|
||||
}
|
||||
|
||||
// @Test
|
||||
// void testImageUrlFailuresThrowExceptionAndBuilderRemainsUsable() {
|
||||
// OllamaChatRequestBuilder builder = OllamaChatRequestBuilder.builder().withModel("m");
|
||||
// String invalidUrl = "ht!tp:/bad_url"; // clearly invalid URL format
|
||||
//
|
||||
// // Exception should be thrown for invalid URL
|
||||
// assertThrows(
|
||||
// Exception.class,
|
||||
// () -> {
|
||||
// builder.withMessage(
|
||||
// OllamaChatMessageRole.USER, "hi", Collections.emptyList(),
|
||||
// invalidUrl);
|
||||
// });
|
||||
//
|
||||
// OllamaChatRequest req =
|
||||
// builder.withMessage(OllamaChatMessageRole.USER, "hello",
|
||||
// Collections.emptyList())
|
||||
// .build();
|
||||
//
|
||||
// assertNotNull(req.getMessages());
|
||||
// assert (!req.getMessages().isEmpty());
|
||||
// OllamaChatMessage msg = req.getMessages().get(0);
|
||||
// assertNotNull(msg.getResponse());
|
||||
// }
|
||||
}
|
||||
|
@ -67,9 +67,9 @@ class TestOptionsAndUtils {
|
||||
|
||||
@Test
|
||||
void testOptionsBuilderRejectsUnsupportedCustomType() {
|
||||
OptionsBuilder builder = new OptionsBuilder();
|
||||
assertThrows(
|
||||
IllegalArgumentException.class, () -> builder.setCustomOption("bad", new Object()));
|
||||
IllegalArgumentException.class,
|
||||
() -> new OptionsBuilder().setCustomOption("bad", new Object()));
|
||||
}
|
||||
|
||||
@Test
|
||||
|
@ -1,52 +0,0 @@
|
||||
/*
|
||||
* Ollama4j - Java library for interacting with Ollama server.
|
||||
* Copyright (c) 2025 Amith Koujalgi and contributors.
|
||||
*
|
||||
* Licensed under the MIT License (the "License");
|
||||
* you may not use this file except in compliance with the License.
|
||||
*
|
||||
*/
|
||||
package io.github.ollama4j.unittests;
|
||||
|
||||
import static org.junit.jupiter.api.Assertions.*;
|
||||
|
||||
class TestToolRegistry {
|
||||
//
|
||||
// @Test
|
||||
// void testAddAndGetToolFunction() {
|
||||
// ToolRegistry registry = new ToolRegistry();
|
||||
// ToolFunction fn = args -> "ok:" + args.get("x");
|
||||
//
|
||||
// Tools.ToolSpecification spec =
|
||||
// Tools.ToolSpecification.builder()
|
||||
// .functionName("test")
|
||||
// .functionDescription("desc")
|
||||
// .toolFunction(fn)
|
||||
// .build();
|
||||
//
|
||||
// registry.addTool("test", spec);
|
||||
// ToolFunction retrieved = registry.getToolFunction("test");
|
||||
// assertNotNull(retrieved);
|
||||
// assertEquals("ok:42", retrieved.apply(Map.of("x", 42)));
|
||||
// }
|
||||
//
|
||||
// @Test
|
||||
// void testGetUnknownReturnsNull() {
|
||||
// ToolRegistry registry = new ToolRegistry();
|
||||
// assertNull(registry.getToolFunction("nope"));
|
||||
// }
|
||||
//
|
||||
// @Test
|
||||
// void testClearRemovesAll() {
|
||||
// ToolRegistry registry = new ToolRegistry();
|
||||
// registry.addTool("a", Tools.ToolSpecification.builder().toolFunction(args ->
|
||||
// 1).build());
|
||||
// registry.addTool("b", Tools.ToolSpecification.builder().toolFunction(args ->
|
||||
// 2).build());
|
||||
// assertFalse(registry.getRegisteredSpecs().isEmpty());
|
||||
// registry.clear();
|
||||
// assertTrue(registry.getRegisteredSpecs().isEmpty());
|
||||
// assertNull(registry.getToolFunction("a"));
|
||||
// assertNull(registry.getToolFunction("b"));
|
||||
// }
|
||||
}
|
@ -1,67 +0,0 @@
|
||||
/*
|
||||
* Ollama4j - Java library for interacting with Ollama server.
|
||||
* Copyright (c) 2025 Amith Koujalgi and contributors.
|
||||
*
|
||||
* Licensed under the MIT License (the "License");
|
||||
* you may not use this file except in compliance with the License.
|
||||
*
|
||||
*/
|
||||
package io.github.ollama4j.unittests;
|
||||
|
||||
class TestToolsPromptBuilder {
|
||||
//
|
||||
// @Test
|
||||
// void testPromptBuilderIncludesToolsAndPrompt() throws JsonProcessingException {
|
||||
// Tools.PromptFuncDefinition.Property cityProp =
|
||||
// Tools.PromptFuncDefinition.Property.builder()
|
||||
// .type("string")
|
||||
// .description("city name")
|
||||
// .required(true)
|
||||
// .build();
|
||||
//
|
||||
// Tools.PromptFuncDefinition.Property unitsProp =
|
||||
// Tools.PromptFuncDefinition.Property.builder()
|
||||
// .type("string")
|
||||
// .description("units")
|
||||
// .enumValues(List.of("metric", "imperial"))
|
||||
// .required(false)
|
||||
// .build();
|
||||
//
|
||||
// Tools.PromptFuncDefinition.Parameters params =
|
||||
// Tools.PromptFuncDefinition.Parameters.builder()
|
||||
// .type("object")
|
||||
// .properties(Map.of("city", cityProp, "units", unitsProp))
|
||||
// .build();
|
||||
//
|
||||
// Tools.PromptFuncDefinition.PromptFuncSpec spec =
|
||||
// Tools.PromptFuncDefinition.PromptFuncSpec.builder()
|
||||
// .name("getWeather")
|
||||
// .description("Get weather for a city")
|
||||
// .parameters(params)
|
||||
// .build();
|
||||
//
|
||||
// Tools.PromptFuncDefinition def =
|
||||
// Tools.PromptFuncDefinition.builder().type("function").function(spec).build();
|
||||
//
|
||||
// Tools.ToolSpecification toolSpec =
|
||||
// Tools.ToolSpecification.builder()
|
||||
// .functionName("getWeather")
|
||||
// .functionDescription("Get weather for a city")
|
||||
// .toolPrompt(def)
|
||||
// .build();
|
||||
//
|
||||
// Tools.PromptBuilder pb =
|
||||
// new Tools.PromptBuilder()
|
||||
// .withToolSpecification(toolSpec)
|
||||
// .withPrompt("Tell me the weather.");
|
||||
//
|
||||
// String built = pb.build();
|
||||
// assertTrue(built.contains("[AVAILABLE_TOOLS]"));
|
||||
// assertTrue(built.contains("[/AVAILABLE_TOOLS]"));
|
||||
// assertTrue(built.contains("[INST]"));
|
||||
// assertTrue(built.contains("Tell me the weather."));
|
||||
// assertTrue(built.contains("\"name\":\"getWeather\""));
|
||||
// assertTrue(built.contains("\"required\":[\"city\"]"));
|
||||
// assertTrue(built.contains("\"enum\":[\"metric\",\"imperial\"]"));
|
||||
// }
|
||||
}
|
Loading…
x
Reference in New Issue
Block a user