mirror of
https://github.com/amithkoujalgi/ollama4j.git
synced 2025-10-14 09:28:58 +02:00
Improve error handling and code clarity across modules
Enhanced error handling for image URL loading in OllamaChatRequestBuilder, ensuring exceptions are thrown and logged appropriately. Updated test cases to reflect new exception behavior. Improved documentation and code clarity in WeatherTool and test classes. Refactored JSON parsing in response models for conciseness. Minor cleanup in pom.xml and integration test comments for better maintainability.
This commit is contained in:
parent
fe87c4ccc8
commit
7788f954d6
2
pom.xml
2
pom.xml
@ -169,8 +169,6 @@
|
|||||||
<artifactId>spotless-maven-plugin</artifactId>
|
<artifactId>spotless-maven-plugin</artifactId>
|
||||||
<version>2.46.1</version>
|
<version>2.46.1</version>
|
||||||
<configuration>
|
<configuration>
|
||||||
<!-- <!– optional: limit format enforcement to just the files changed by this feature branch –>-->
|
|
||||||
<!-- <ratchetFrom>origin/main</ratchetFrom>-->
|
|
||||||
<formats>
|
<formats>
|
||||||
<!-- you can define as many formats as you want, each is independent -->
|
<!-- you can define as many formats as you want, each is independent -->
|
||||||
<format>
|
<format>
|
||||||
|
@ -727,7 +727,8 @@ public class OllamaAPI {
|
|||||||
LOG.debug("Model response:\n{}", ollamaResult);
|
LOG.debug("Model response:\n{}", ollamaResult);
|
||||||
return ollamaResult;
|
return ollamaResult;
|
||||||
} else {
|
} else {
|
||||||
LOG.debug("Model response:\n{}", Utils.toJSON(responseBody));
|
String errorResponse = Utils.toJSON(responseBody);
|
||||||
|
LOG.debug("Model response:\n{}", errorResponse);
|
||||||
throw new OllamaBaseException(statusCode + " - " + responseBody);
|
throw new OllamaBaseException(statusCode + " - " + responseBody);
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
@ -100,7 +100,8 @@ public class OllamaChatRequestBuilder {
|
|||||||
OllamaChatMessageRole role,
|
OllamaChatMessageRole role,
|
||||||
String content,
|
String content,
|
||||||
List<OllamaChatToolCalls> toolCalls,
|
List<OllamaChatToolCalls> toolCalls,
|
||||||
String... imageUrls) {
|
String... imageUrls)
|
||||||
|
throws IOException, InterruptedException {
|
||||||
List<OllamaChatMessage> messages = this.request.getMessages();
|
List<OllamaChatMessage> messages = this.request.getMessages();
|
||||||
List<byte[]> binaryImages = null;
|
List<byte[]> binaryImages = null;
|
||||||
if (imageUrls.length > 0) {
|
if (imageUrls.length > 0) {
|
||||||
@ -112,11 +113,18 @@ public class OllamaChatRequestBuilder {
|
|||||||
imageUrl,
|
imageUrl,
|
||||||
imageURLConnectTimeoutSeconds,
|
imageURLConnectTimeoutSeconds,
|
||||||
imageURLReadTimeoutSeconds));
|
imageURLReadTimeoutSeconds));
|
||||||
} catch (Exception e) {
|
} catch (InterruptedException e) {
|
||||||
LOG.warn(
|
LOG.error(
|
||||||
"Loading image from URL '{}' failed, will not add to message!",
|
"Failed to load image from URL: {}. Cause: {}",
|
||||||
imageUrl,
|
imageUrl,
|
||||||
e);
|
e.getMessage());
|
||||||
|
throw e;
|
||||||
|
} catch (IOException e) {
|
||||||
|
LOG.warn(
|
||||||
|
"Failed to load image from URL: {}. Cause: {}",
|
||||||
|
imageUrl,
|
||||||
|
e.getMessage());
|
||||||
|
throw e;
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
@ -21,8 +21,12 @@ public abstract class OllamaCommonRequest {
|
|||||||
|
|
||||||
protected String model;
|
protected String model;
|
||||||
|
|
||||||
// @JsonSerialize(using = BooleanToJsonFormatFlagSerializer.class)
|
/**
|
||||||
// this can either be set to format=json or format={"key1": "val1", "key2": "val2"}
|
* The value can either be
|
||||||
|
* <pre>{@code json }</pre>
|
||||||
|
* or
|
||||||
|
* <pre>{@code {"key1": "val1", "key2": "val2"} }</pre>
|
||||||
|
*/
|
||||||
@JsonProperty(value = "format", required = false, defaultValue = "json")
|
@JsonProperty(value = "format", required = false, defaultValue = "json")
|
||||||
protected Object format;
|
protected Object format;
|
||||||
|
|
||||||
|
@ -112,10 +112,8 @@ public class OllamaResult {
|
|||||||
throw new IllegalArgumentException("Response is not a valid JSON object");
|
throw new IllegalArgumentException("Response is not a valid JSON object");
|
||||||
}
|
}
|
||||||
|
|
||||||
Map<String, Object> response =
|
return getObjectMapper()
|
||||||
getObjectMapper()
|
.readValue(responseStr, new TypeReference<Map<String, Object>>() {});
|
||||||
.readValue(responseStr, new TypeReference<Map<String, Object>>() {});
|
|
||||||
return response;
|
|
||||||
} catch (JsonProcessingException e) {
|
} catch (JsonProcessingException e) {
|
||||||
throw new IllegalArgumentException(
|
throw new IllegalArgumentException(
|
||||||
"Failed to parse response as JSON: " + e.getMessage(), e);
|
"Failed to parse response as JSON: " + e.getMessage(), e);
|
||||||
|
@ -65,12 +65,8 @@ public class OllamaStructuredResult {
|
|||||||
*/
|
*/
|
||||||
public Map<String, Object> getStructuredResponse() {
|
public Map<String, Object> getStructuredResponse() {
|
||||||
try {
|
try {
|
||||||
Map<String, Object> response =
|
return getObjectMapper()
|
||||||
getObjectMapper()
|
.readValue(this.getResponse(), new TypeReference<Map<String, Object>>() {});
|
||||||
.readValue(
|
|
||||||
this.getResponse(),
|
|
||||||
new TypeReference<Map<String, Object>>() {});
|
|
||||||
return response;
|
|
||||||
} catch (JsonProcessingException e) {
|
} catch (JsonProcessingException e) {
|
||||||
throw new RuntimeException(e);
|
throw new RuntimeException(e);
|
||||||
}
|
}
|
||||||
|
@ -15,7 +15,14 @@ import java.util.Map;
|
|||||||
public class WeatherTool {
|
public class WeatherTool {
|
||||||
private String paramCityName = "cityName";
|
private String paramCityName = "cityName";
|
||||||
|
|
||||||
public WeatherTool() {}
|
/**
|
||||||
|
* Default constructor for WeatherTool.
|
||||||
|
* This constructor is intentionally left empty because no initialization is required
|
||||||
|
* for this sample tool. If future state or dependencies are needed, they can be added here.
|
||||||
|
*/
|
||||||
|
public WeatherTool() {
|
||||||
|
// No initialization required
|
||||||
|
}
|
||||||
|
|
||||||
public String getCurrentWeather(Map<String, Object> arguments) {
|
public String getCurrentWeather(Map<String, Object> arguments) {
|
||||||
String city = (String) arguments.get(paramCityName);
|
String city = (String) arguments.get(paramCityName);
|
||||||
|
@ -619,25 +619,27 @@ class OllamaAPIIntegrationTest {
|
|||||||
OllamaChatMessageRole.ASSISTANT.getRoleName(),
|
OllamaChatMessageRole.ASSISTANT.getRoleName(),
|
||||||
chatResult.getResponseModel().getMessage().getRole().getRoleName());
|
chatResult.getResponseModel().getMessage().getRole().getRoleName());
|
||||||
|
|
||||||
// Reproducing this scenario consistently is challenging, as the model's behavior can vary.
|
/*
|
||||||
// Therefore, these checks are currently skipped until a more reliable approach is found.
|
* Reproducing this scenario consistently is challenging, as the model's behavior can vary.
|
||||||
|
* Therefore, these checks are currently skipped until a more reliable approach is found.
|
||||||
// List<OllamaChatToolCalls> toolCalls =
|
*
|
||||||
// chatResult.getChatHistory().get(1).getToolCalls();
|
* // List<OllamaChatToolCalls> toolCalls =
|
||||||
// assertEquals(1, toolCalls.size());
|
* // chatResult.getChatHistory().get(1).getToolCalls();
|
||||||
// OllamaToolCallsFunction function = toolCalls.get(0).getFunction();
|
* // assertEquals(1, toolCalls.size());
|
||||||
// assertEquals("sayHello", function.getName());
|
* // OllamaToolCallsFunction function = toolCalls.get(0).getFunction();
|
||||||
// assertEquals(2, function.getArguments().size());
|
* // assertEquals("sayHello", function.getName());
|
||||||
// Object name = function.getArguments().get("name");
|
* // assertEquals(2, function.getArguments().size());
|
||||||
// assertNotNull(name);
|
* // Object name = function.getArguments().get("name");
|
||||||
// assertEquals("Rahul", name);
|
* // assertNotNull(name);
|
||||||
// Object numberOfHearts = function.getArguments().get("numberOfHearts");
|
* // assertEquals("Rahul", name);
|
||||||
// assertNotNull(numberOfHearts);
|
* // Object numberOfHearts = function.getArguments().get("numberOfHearts");
|
||||||
// assertTrue(Integer.parseInt(numberOfHearts.toString()) > 1);
|
* // assertNotNull(numberOfHearts);
|
||||||
// assertTrue(chatResult.getChatHistory().size() > 2);
|
* // assertTrue(Integer.parseInt(numberOfHearts.toString()) > 1);
|
||||||
// List<OllamaChatToolCalls> finalToolCalls =
|
* // assertTrue(chatResult.getChatHistory().size() > 2);
|
||||||
// chatResult.getResponseModel().getMessage().getToolCalls();
|
* // List<OllamaChatToolCalls> finalToolCalls =
|
||||||
// assertNull(finalToolCalls);
|
* // chatResult.getResponseModel().getMessage().getToolCalls();
|
||||||
|
* // assertNull(finalToolCalls);
|
||||||
|
*/
|
||||||
}
|
}
|
||||||
|
|
||||||
@Test
|
@Test
|
||||||
|
@ -40,14 +40,18 @@ class TestOllamaChatRequestBuilder {
|
|||||||
}
|
}
|
||||||
|
|
||||||
@Test
|
@Test
|
||||||
void testImageUrlFailuresAreHandledAndBuilderRemainsUsable() {
|
void testImageUrlFailuresThrowExceptionAndBuilderRemainsUsable() {
|
||||||
OllamaChatRequestBuilder builder = OllamaChatRequestBuilder.getInstance("m");
|
OllamaChatRequestBuilder builder = OllamaChatRequestBuilder.getInstance("m");
|
||||||
String invalidUrl = "ht!tp:/bad_url"; // clearly invalid URL format
|
String invalidUrl = "ht!tp:/bad_url"; // clearly invalid URL format
|
||||||
|
|
||||||
// No exception should be thrown; builder should handle invalid URL gracefully
|
// Exception should be thrown for invalid URL
|
||||||
builder.withMessage(OllamaChatMessageRole.USER, "hi", Collections.emptyList(), invalidUrl);
|
assertThrows(
|
||||||
|
Exception.class,
|
||||||
|
() -> {
|
||||||
|
builder.withMessage(
|
||||||
|
OllamaChatMessageRole.USER, "hi", Collections.emptyList(), invalidUrl);
|
||||||
|
});
|
||||||
|
|
||||||
// The builder should still be usable after the exception
|
|
||||||
OllamaChatRequest req =
|
OllamaChatRequest req =
|
||||||
builder.withMessage(OllamaChatMessageRole.USER, "hello", Collections.emptyList())
|
builder.withMessage(OllamaChatMessageRole.USER, "hello", Collections.emptyList())
|
||||||
.build();
|
.build();
|
||||||
|
@ -50,9 +50,17 @@ class TestOllamaRequestBody {
|
|||||||
}
|
}
|
||||||
|
|
||||||
@Override
|
@Override
|
||||||
public void onError(Throwable throwable) {}
|
// This method is intentionally left empty because, for this test,
|
||||||
|
// we do not expect any errors to occur during synchronous publishing.
|
||||||
|
// If an error does occur, the test will fail elsewhere.
|
||||||
|
public void onError(Throwable throwable) {
|
||||||
|
// No action needed for this test
|
||||||
|
}
|
||||||
|
|
||||||
@Override
|
@Override
|
||||||
|
// This method is intentionally left empty because for this test,
|
||||||
|
// all the data is synchronously delivered by the publisher, so no action is
|
||||||
|
// needed on completion.
|
||||||
public void onComplete() {}
|
public void onComplete() {}
|
||||||
});
|
});
|
||||||
|
|
||||||
|
@ -67,9 +67,9 @@ class TestOptionsAndUtils {
|
|||||||
|
|
||||||
@Test
|
@Test
|
||||||
void testOptionsBuilderRejectsUnsupportedCustomType() {
|
void testOptionsBuilderRejectsUnsupportedCustomType() {
|
||||||
OptionsBuilder builder = new OptionsBuilder();
|
|
||||||
assertThrows(
|
assertThrows(
|
||||||
IllegalArgumentException.class, () -> builder.setCustomOption("bad", new Object()));
|
IllegalArgumentException.class,
|
||||||
|
() -> new OptionsBuilder().setCustomOption("bad", new Object()));
|
||||||
}
|
}
|
||||||
|
|
||||||
@Test
|
@Test
|
||||||
|
@ -104,11 +104,9 @@ public class TestChatRequestSerialization extends AbstractSerializationTest<Olla
|
|||||||
assertThrowsExactly(
|
assertThrowsExactly(
|
||||||
IllegalArgumentException.class,
|
IllegalArgumentException.class,
|
||||||
() -> {
|
() -> {
|
||||||
OllamaChatRequest req =
|
builder.withMessage(OllamaChatMessageRole.USER, "Some prompt")
|
||||||
builder.withMessage(OllamaChatMessageRole.USER, "Some prompt")
|
.withOptions(b.setCustomOption("cust_obj", new Object()).build())
|
||||||
.withOptions(
|
.build();
|
||||||
b.setCustomOption("cust_obj", new Object()).build())
|
|
||||||
.build();
|
|
||||||
});
|
});
|
||||||
}
|
}
|
||||||
|
|
||||||
@ -120,7 +118,8 @@ public class TestChatRequestSerialization extends AbstractSerializationTest<Olla
|
|||||||
.build();
|
.build();
|
||||||
|
|
||||||
String jsonRequest = serialize(req);
|
String jsonRequest = serialize(req);
|
||||||
// no jackson deserialization as format property is not boolean ==> omit as deserialization
|
// no jackson deserialization as format property is not boolean ==> omit as
|
||||||
|
// deserialization
|
||||||
// of request is never used in real code anyways
|
// of request is never used in real code anyways
|
||||||
JSONObject jsonObject = new JSONObject(jsonRequest);
|
JSONObject jsonObject = new JSONObject(jsonRequest);
|
||||||
String requestFormatProperty = jsonObject.getString("format");
|
String requestFormatProperty = jsonObject.getString("format");
|
||||||
|
@ -16,8 +16,7 @@ import io.github.ollama4j.utils.OptionsBuilder;
|
|||||||
import org.junit.jupiter.api.BeforeEach;
|
import org.junit.jupiter.api.BeforeEach;
|
||||||
import org.junit.jupiter.api.Test;
|
import org.junit.jupiter.api.Test;
|
||||||
|
|
||||||
public class TestEmbedRequestSerialization
|
class TestEmbedRequestSerialization extends AbstractSerializationTest<OllamaEmbedRequestModel> {
|
||||||
extends AbstractSerializationTest<OllamaEmbedRequestModel> {
|
|
||||||
|
|
||||||
private OllamaEmbedRequestBuilder builder;
|
private OllamaEmbedRequestBuilder builder;
|
||||||
|
|
||||||
|
@ -17,8 +17,7 @@ import org.json.JSONObject;
|
|||||||
import org.junit.jupiter.api.BeforeEach;
|
import org.junit.jupiter.api.BeforeEach;
|
||||||
import org.junit.jupiter.api.Test;
|
import org.junit.jupiter.api.Test;
|
||||||
|
|
||||||
public class TestGenerateRequestSerialization
|
class TestGenerateRequestSerialization extends AbstractSerializationTest<OllamaGenerateRequest> {
|
||||||
extends AbstractSerializationTest<OllamaGenerateRequest> {
|
|
||||||
|
|
||||||
private OllamaGenerateRequestBuilder builder;
|
private OllamaGenerateRequestBuilder builder;
|
||||||
|
|
||||||
|
@ -19,8 +19,7 @@ import org.junit.jupiter.api.Test;
|
|||||||
* error responses from Ollama server that return HTTP 200 with error messages
|
* error responses from Ollama server that return HTTP 200 with error messages
|
||||||
* in the JSON body.
|
* in the JSON body.
|
||||||
*/
|
*/
|
||||||
public class TestModelPullResponseSerialization
|
class TestModelPullResponseSerialization extends AbstractSerializationTest<ModelPullResponse> {
|
||||||
extends AbstractSerializationTest<ModelPullResponse> {
|
|
||||||
|
|
||||||
/**
|
/**
|
||||||
* Test the specific error case reported in GitHub issue #138.
|
* Test the specific error case reported in GitHub issue #138.
|
||||||
|
Loading…
x
Reference in New Issue
Block a user