- Updated Makefile to add a new remote integration test command.

- Updated docs – Enhanced DBQueryFunction to validate input arguments and throw a RuntimeException if required arguments are missing.
- Updated docs – Refactored tool specifications for fuel price, weather, and employee details to use a unified prompt function structure.  (Addresses #116).
- Improved javadoc for `chatStreaming()` API. (Addresses #115).
- Introduced `ToolInvocationException` to handle errors during tool invocation in OllamaAPI. (Addresses #117).
- Updated integration tests to include `ToolInvocationException` in method signatures for better error handling.
This commit is contained in:
amithkoujalgi 2025-04-06 23:05:26 +05:30
parent 70b4a7961a
commit a2d95a052a
No known key found for this signature in database
GPG Key ID: E29A37746AF94B70
5 changed files with 233 additions and 68 deletions

View File

@ -18,8 +18,8 @@ unit-tests:
integration-tests: integration-tests:
export USE_EXTERNAL_OLLAMA_HOST=false && mvn clean verify -Pintegration-tests export USE_EXTERNAL_OLLAMA_HOST=false && mvn clean verify -Pintegration-tests
integration-tests-local: integration-tests-remote:
export USE_EXTERNAL_OLLAMA_HOST=true && export OLLAMA_HOST=http://localhost:11434 && mvn clean verify -Pintegration-tests -Dgpg.skip=true export USE_EXTERNAL_OLLAMA_HOST=true && export OLLAMA_HOST=http://192.168.29.223:11434 && mvn clean verify -Pintegration-tests -Dgpg.skip=true
doxygen: doxygen:
doxygen Doxyfile doxygen Doxyfile

View File

@ -61,6 +61,9 @@ details.
class DBQueryFunction implements ToolFunction { class DBQueryFunction implements ToolFunction {
@Override @Override
public Object apply(Map<String, Object> arguments) { public Object apply(Map<String, Object> arguments) {
if (arguments == null || arguments.isEmpty() || arguments.get("employee-name") == null || arguments.get("employee-address") == null || arguments.get("employee-phone") == null) {
throw new RuntimeException("Tool was called but the model failed to provide all the required arguments.");
}
// perform DB operations here // perform DB operations here
return String.format("Employee Details {ID: %s, Name: %s, Address: %s, Phone: %s}", UUID.randomUUID(), arguments.get("employee-name").toString(), arguments.get("employee-address").toString(), arguments.get("employee-phone").toString()); return String.format("Employee Details {ID: %s, Name: %s, Address: %s, Phone: %s}", UUID.randomUUID(), arguments.get("employee-name").toString(), arguments.get("employee-address").toString(), arguments.get("employee-phone").toString());
} }
@ -78,14 +81,39 @@ Lets define a sample tool specification called **Fuel Price Tool** for getting t
Tools.ToolSpecification fuelPriceToolSpecification = Tools.ToolSpecification.builder() Tools.ToolSpecification fuelPriceToolSpecification = Tools.ToolSpecification.builder()
.functionName("current-fuel-price") .functionName("current-fuel-price")
.functionDescription("Get current fuel price") .functionDescription("Get current fuel price")
.toolFunction(SampleTools::getCurrentFuelPrice)
.toolPrompt(
Tools.PromptFuncDefinition.builder()
.type("prompt")
.function(
Tools.PromptFuncDefinition.PromptFuncSpec.builder()
.name("get-location-fuel-info")
.description("Get location and fuel type details")
.parameters(
Tools.PromptFuncDefinition.Parameters.builder()
.type("object")
.properties( .properties(
new Tools.PropsBuilder() Map.of(
.withProperty("location", Tools.PromptFuncDefinition.Property.builder().type("string").description("The city, e.g. New Delhi, India").required(true).build()) "location", Tools.PromptFuncDefinition.Property.builder()
.withProperty("fuelType", Tools.PromptFuncDefinition.Property.builder().type("string").description("The fuel type.").enumValues(Arrays.asList("petrol", "diesel")).required(true).build()) .type("string")
.description("The city, e.g. New Delhi, India")
.required(true)
.build(),
"fuelType", Tools.PromptFuncDefinition.Property.builder()
.type("string")
.description("The fuel type.")
.enumValues(Arrays.asList("petrol", "diesel"))
.required(true)
.build() .build()
) )
.toolDefinition(SampleTools::getCurrentFuelPrice) )
.build(); .required(java.util.List.of("location", "fuelType"))
.build()
)
.build()
)
.build()
).build();
``` ```
Lets also define a sample tool specification called **Weather Tool** for getting the current weather. Lets also define a sample tool specification called **Weather Tool** for getting the current weather.
@ -97,13 +125,33 @@ Lets also define a sample tool specification called **Weather Tool** for getting
Tools.ToolSpecification weatherToolSpecification = Tools.ToolSpecification.builder() Tools.ToolSpecification weatherToolSpecification = Tools.ToolSpecification.builder()
.functionName("current-weather") .functionName("current-weather")
.functionDescription("Get current weather") .functionDescription("Get current weather")
.toolFunction(SampleTools::getCurrentWeather)
.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( .properties(
new Tools.PropsBuilder() Map.of(
.withProperty("city", Tools.PromptFuncDefinition.Property.builder().type("string").description("The city, e.g. New Delhi, India").required(true).build()) "city", Tools.PromptFuncDefinition.Property.builder()
.type("string")
.description("The city, e.g. New Delhi, India")
.required(true)
.build() .build()
) )
.toolDefinition(SampleTools::getCurrentWeather) )
.build(); .required(java.util.List.of("city"))
.build()
)
.build()
)
.build()
).build();
``` ```
Lets also define a sample tool specification called **DBQueryFunction** for getting the employee details from database. Lets also define a sample tool specification called **DBQueryFunction** for getting the employee details from database.
@ -115,14 +163,43 @@ Lets also define a sample tool specification called **DBQueryFunction** for gett
Tools.ToolSpecification databaseQueryToolSpecification = Tools.ToolSpecification.builder() Tools.ToolSpecification databaseQueryToolSpecification = Tools.ToolSpecification.builder()
.functionName("get-employee-details") .functionName("get-employee-details")
.functionDescription("Get employee details from the database") .functionDescription("Get employee details from the database")
.toolFunction(new DBQueryFunction())
.toolPrompt(
Tools.PromptFuncDefinition.builder()
.type("prompt")
.function(
Tools.PromptFuncDefinition.PromptFuncSpec.builder()
.name("get-employee-details")
.description("Get employee details from the database")
.parameters(
Tools.PromptFuncDefinition.Parameters.builder()
.type("object")
.properties( .properties(
new Tools.PropsBuilder() Map.of(
.withProperty("employee-name", Tools.PromptFuncDefinition.Property.builder().type("string").description("The name of the employee, e.g. John Doe").required(true).build()) "employee-name", Tools.PromptFuncDefinition.Property.builder()
.withProperty("employee-address", Tools.PromptFuncDefinition.Property.builder().type("string").description("The address of the employee, Always return a random value. e.g. Roy St, Bengaluru, India").required(true).build()) .type("string")
.withProperty("employee-phone", Tools.PromptFuncDefinition.Property.builder().type("string").description("The phone number of the employee. Always return a random value. e.g. 9911002233").required(true).build()) .description("The name of the employee, e.g. John Doe")
.required(true)
.build(),
"employee-address", Tools.PromptFuncDefinition.Property.builder()
.type("string")
.description("The address of the employee, Always return a random value. e.g. Roy St, Bengaluru, India")
.required(true)
.build(),
"employee-phone", Tools.PromptFuncDefinition.Property.builder()
.type("string")
.description("The phone number of the employee. Always return a random value. e.g. 9911002233")
.required(true)
.build()
)
)
.required(java.util.List.of("employee-name", "employee-address", "employee-phone"))
.build()
)
.build()
)
.build() .build()
) )
.toolDefinition(new DBQueryFunction())
.build(); .build();
``` ```
@ -239,37 +316,111 @@ public class FunctionCallingWithMistralExample {
Tools.ToolSpecification fuelPriceToolSpecification = Tools.ToolSpecification.builder() Tools.ToolSpecification fuelPriceToolSpecification = Tools.ToolSpecification.builder()
.functionName("current-fuel-price") .functionName("current-fuel-price")
.functionDescription("Get current fuel price") .functionDescription("Get current fuel price")
.toolFunction(SampleTools::getCurrentFuelPrice)
.toolPrompt(
Tools.PromptFuncDefinition.builder()
.type("prompt")
.function(
Tools.PromptFuncDefinition.PromptFuncSpec.builder()
.name("get-location-fuel-info")
.description("Get location and fuel type details")
.parameters(
Tools.PromptFuncDefinition.Parameters.builder()
.type("object")
.properties( .properties(
new Tools.PropsBuilder() Map.of(
.withProperty("location", Tools.PromptFuncDefinition.Property.builder().type("string").description("The city, e.g. New Delhi, India").required(true).build()) "location", Tools.PromptFuncDefinition.Property.builder()
.withProperty("fuelType", Tools.PromptFuncDefinition.Property.builder().type("string").description("The fuel type.").enumValues(Arrays.asList("petrol", "diesel")).required(true).build()) .type("string")
.description("The city, e.g. New Delhi, India")
.required(true)
.build(),
"fuelType", Tools.PromptFuncDefinition.Property.builder()
.type("string")
.description("The fuel type.")
.enumValues(Arrays.asList("petrol", "diesel"))
.required(true)
.build() .build()
) )
.toolDefinition(SampleTools::getCurrentFuelPrice) )
.build(); .required(java.util.List.of("location", "fuelType"))
.build()
)
.build()
)
.build()
).build();
Tools.ToolSpecification weatherToolSpecification = Tools.ToolSpecification.builder() Tools.ToolSpecification weatherToolSpecification = Tools.ToolSpecification.builder()
.functionName("current-weather") .functionName("current-weather")
.functionDescription("Get current weather") .functionDescription("Get current weather")
.toolFunction(SampleTools::getCurrentWeather)
.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( .properties(
new Tools.PropsBuilder() Map.of(
.withProperty("city", Tools.PromptFuncDefinition.Property.builder().type("string").description("The city, e.g. New Delhi, India").required(true).build()) "city", Tools.PromptFuncDefinition.Property.builder()
.type("string")
.description("The city, e.g. New Delhi, India")
.required(true)
.build() .build()
) )
.toolDefinition(SampleTools::getCurrentWeather) )
.build(); .required(java.util.List.of("city"))
.build()
)
.build()
)
.build()
).build();
Tools.ToolSpecification databaseQueryToolSpecification = Tools.ToolSpecification.builder() Tools.ToolSpecification databaseQueryToolSpecification = Tools.ToolSpecification.builder()
.functionName("get-employee-details") .functionName("get-employee-details")
.functionDescription("Get employee details from the database") .functionDescription("Get employee details from the database")
.toolFunction(new DBQueryFunction())
.toolPrompt(
Tools.PromptFuncDefinition.builder()
.type("prompt")
.function(
Tools.PromptFuncDefinition.PromptFuncSpec.builder()
.name("get-employee-details")
.description("Get employee details from the database")
.parameters(
Tools.PromptFuncDefinition.Parameters.builder()
.type("object")
.properties( .properties(
new Tools.PropsBuilder() Map.of(
.withProperty("employee-name", Tools.PromptFuncDefinition.Property.builder().type("string").description("The name of the employee, e.g. John Doe").required(true).build()) "employee-name", Tools.PromptFuncDefinition.Property.builder()
.withProperty("employee-address", Tools.PromptFuncDefinition.Property.builder().type("string").description("The address of the employee, Always return a random value. e.g. Roy St, Bengaluru, India").required(true).build()) .type("string")
.withProperty("employee-phone", Tools.PromptFuncDefinition.Property.builder().type("string").description("The phone number of the employee. Always return a random value. e.g. 9911002233").required(true).build()) .description("The name of the employee, e.g. John Doe")
.required(true)
.build(),
"employee-address", Tools.PromptFuncDefinition.Property.builder()
.type("string")
.description("The address of the employee, Always return a random value. e.g. Roy St, Bengaluru, India")
.required(true)
.build(),
"employee-phone", Tools.PromptFuncDefinition.Property.builder()
.type("string")
.description("The phone number of the employee. Always return a random value. e.g. 9911002233")
.required(true)
.build()
)
)
.required(java.util.List.of("employee-name", "employee-address", "employee-phone"))
.build()
)
.build()
)
.build() .build()
) )
.toolDefinition(new DBQueryFunction())
.build(); .build();
ollamaAPI.registerTool(fuelPriceToolSpecification); ollamaAPI.registerTool(fuelPriceToolSpecification);
@ -326,6 +477,9 @@ class SampleTools {
class DBQueryFunction implements ToolFunction { class DBQueryFunction implements ToolFunction {
@Override @Override
public Object apply(Map<String, Object> arguments) { public Object apply(Map<String, Object> arguments) {
if (arguments == null || arguments.isEmpty() || arguments.get("employee-name") == null || arguments.get("employee-address") == null || arguments.get("employee-phone") == null) {
throw new RuntimeException("Tool was called but the model failed to provide all the required arguments.");
}
// perform DB operations here // perform DB operations here
return String.format("Employee Details {ID: %s, Name: %s, Address: %s, Phone: %s}", UUID.randomUUID(), arguments.get("employee-name").toString(), arguments.get("employee-address").toString(), arguments.get("employee-phone").toString()); return String.format("Employee Details {ID: %s, Name: %s, Address: %s, Phone: %s}", UUID.randomUUID(), arguments.get("employee-name").toString(), arguments.get("employee-address").toString(), arguments.get("employee-phone").toString());
} }

View File

@ -1058,7 +1058,7 @@ public class OllamaAPI {
* @param model the ollama model to ask the question to * @param model the ollama model to ask the question to
* @param messages chat history / message stack to send to the model * @param messages chat history / message stack to send to the model
* @return {@link OllamaChatResult} containing the api response and the message * @return {@link OllamaChatResult} containing the api response and the message
* history including the newly aqcuired assistant response. * history including the newly acquired assistant response.
* @throws OllamaBaseException any response code than 200 has been returned * @throws OllamaBaseException any response code than 200 has been returned
* @throws IOException in case the responseStream can not be read * @throws IOException in case the responseStream can not be read
* @throws InterruptedException in case the server is not reachable or network * @throws InterruptedException in case the server is not reachable or network
@ -1066,9 +1066,10 @@ public class OllamaAPI {
* @throws OllamaBaseException if the response indicates an error status * @throws OllamaBaseException if the response indicates an error status
* @throws IOException if an I/O error occurs during the HTTP request * @throws IOException if an I/O error occurs during the HTTP request
* @throws InterruptedException if the operation is interrupted * @throws InterruptedException if the operation is interrupted
* @throws ToolInvocationException if the tool invocation fails
*/ */
public OllamaChatResult chat(String model, List<OllamaChatMessage> messages) public OllamaChatResult chat(String model, List<OllamaChatMessage> messages)
throws OllamaBaseException, IOException, InterruptedException { throws OllamaBaseException, IOException, InterruptedException, ToolInvocationException {
OllamaChatRequestBuilder builder = OllamaChatRequestBuilder.getInstance(model); OllamaChatRequestBuilder builder = OllamaChatRequestBuilder.getInstance(model);
return chat(builder.withMessages(messages).build()); return chat(builder.withMessages(messages).build());
} }
@ -1088,9 +1089,10 @@ public class OllamaAPI {
* @throws OllamaBaseException if the response indicates an error status * @throws OllamaBaseException if the response indicates an error status
* @throws IOException if an I/O error occurs during the HTTP request * @throws IOException if an I/O error occurs during the HTTP request
* @throws InterruptedException if the operation is interrupted * @throws InterruptedException if the operation is interrupted
* @throws ToolInvocationException if the tool invocation fails
*/ */
public OllamaChatResult chat(OllamaChatRequest request) public OllamaChatResult chat(OllamaChatRequest request)
throws OllamaBaseException, IOException, InterruptedException { throws OllamaBaseException, IOException, InterruptedException, ToolInvocationException {
return chat(request, null); return chat(request, null);
} }
@ -1102,7 +1104,7 @@ public class OllamaAPI {
* *
* @param request request object to be sent to the server * @param request request object to be sent to the server
* @param streamHandler callback handler to handle the last message from stream * @param streamHandler callback handler to handle the last message from stream
* (caution: all previous messages from stream will be * (caution: all previous tokens from stream will be
* concatenated) * concatenated)
* @return {@link OllamaChatResult} * @return {@link OllamaChatResult}
* @throws OllamaBaseException any response code than 200 has been returned * @throws OllamaBaseException any response code than 200 has been returned
@ -1112,9 +1114,10 @@ public class OllamaAPI {
* @throws OllamaBaseException if the response indicates an error status * @throws OllamaBaseException if the response indicates an error status
* @throws IOException if an I/O error occurs during the HTTP request * @throws IOException if an I/O error occurs during the HTTP request
* @throws InterruptedException if the operation is interrupted * @throws InterruptedException if the operation is interrupted
* @throws ToolInvocationException if the tool invocation fails
*/ */
public OllamaChatResult chat(OllamaChatRequest request, OllamaStreamHandler streamHandler) public OllamaChatResult chat(OllamaChatRequest request, OllamaStreamHandler streamHandler)
throws OllamaBaseException, IOException, InterruptedException { throws OllamaBaseException, IOException, InterruptedException, ToolInvocationException {
return chatStreaming(request, new OllamaChatStreamObserver(streamHandler)); return chatStreaming(request, new OllamaChatStreamObserver(streamHandler));
} }
@ -1126,7 +1129,7 @@ public class OllamaAPI {
* *
* @param request request object to be sent to the server * @param request request object to be sent to the server
* @param tokenHandler callback handler to handle the last token from stream * @param tokenHandler callback handler to handle the last token from stream
* (caution: all previous messages from stream will be * (caution: the previous tokens from stream will not be
* concatenated) * concatenated)
* @return {@link OllamaChatResult} * @return {@link OllamaChatResult}
* @throws OllamaBaseException any response code than 200 has been returned * @throws OllamaBaseException any response code than 200 has been returned
@ -1138,7 +1141,7 @@ public class OllamaAPI {
* @throws InterruptedException if the operation is interrupted * @throws InterruptedException if the operation is interrupted
*/ */
public OllamaChatResult chatStreaming(OllamaChatRequest request, OllamaTokenHandler tokenHandler) public OllamaChatResult chatStreaming(OllamaChatRequest request, OllamaTokenHandler tokenHandler)
throws OllamaBaseException, IOException, InterruptedException { throws OllamaBaseException, IOException, InterruptedException, ToolInvocationException {
OllamaChatEndpointCaller requestCaller = new OllamaChatEndpointCaller(host, auth, requestTimeoutSeconds, OllamaChatEndpointCaller requestCaller = new OllamaChatEndpointCaller(host, auth, requestTimeoutSeconds,
verbose); verbose);
OllamaChatResult result; OllamaChatResult result;
@ -1161,6 +1164,9 @@ public class OllamaAPI {
for (OllamaChatToolCalls toolCall : toolCalls) { for (OllamaChatToolCalls toolCall : toolCalls) {
String toolName = toolCall.getFunction().getName(); String toolName = toolCall.getFunction().getName();
ToolFunction toolFunction = toolRegistry.getToolFunction(toolName); ToolFunction toolFunction = toolRegistry.getToolFunction(toolName);
if (toolFunction == null) {
throw new ToolInvocationException("Tool function not found: " + toolName);
}
Map<String, Object> arguments = toolCall.getFunction().getArguments(); Map<String, Object> arguments = toolCall.getFunction().getArguments();
Object res = toolFunction.apply(arguments); Object res = toolFunction.apply(arguments);
request.getMessages().add(new OllamaChatMessage(OllamaChatMessageRole.TOOL, request.getMessages().add(new OllamaChatMessage(OllamaChatMessageRole.TOOL,

View File

@ -2,6 +2,10 @@ package io.github.ollama4j.exceptions;
public class ToolInvocationException extends Exception { public class ToolInvocationException extends Exception {
public ToolInvocationException(String s) {
super(s);
}
public ToolInvocationException(String s, Exception e) { public ToolInvocationException(String s, Exception e) {
super(s, e); super(s, e);
} }

View File

@ -3,6 +3,7 @@ package io.github.ollama4j.integrationtests;
import com.fasterxml.jackson.annotation.JsonProperty; import com.fasterxml.jackson.annotation.JsonProperty;
import io.github.ollama4j.OllamaAPI; import io.github.ollama4j.OllamaAPI;
import io.github.ollama4j.exceptions.OllamaBaseException; import io.github.ollama4j.exceptions.OllamaBaseException;
import io.github.ollama4j.exceptions.ToolInvocationException;
import io.github.ollama4j.models.chat.*; import io.github.ollama4j.models.chat.*;
import io.github.ollama4j.models.embeddings.OllamaEmbedResponseModel; import io.github.ollama4j.models.embeddings.OllamaEmbedResponseModel;
import io.github.ollama4j.models.response.LibraryModel; import io.github.ollama4j.models.response.LibraryModel;
@ -233,7 +234,7 @@ public class OllamaAPIIntegrationTest {
@Test @Test
@Order(8) @Order(8)
void testAskModelWithOptions() void testAskModelWithOptions()
throws OllamaBaseException, IOException, URISyntaxException, InterruptedException { throws OllamaBaseException, IOException, URISyntaxException, InterruptedException, ToolInvocationException {
api.pullModel(CHAT_MODEL_INSTRUCT); api.pullModel(CHAT_MODEL_INSTRUCT);
OllamaChatRequestBuilder builder = OllamaChatRequestBuilder.getInstance(CHAT_MODEL_INSTRUCT); OllamaChatRequestBuilder builder = OllamaChatRequestBuilder.getInstance(CHAT_MODEL_INSTRUCT);
@ -253,7 +254,7 @@ public class OllamaAPIIntegrationTest {
@Test @Test
@Order(9) @Order(9)
void testChatWithSystemPrompt() void testChatWithSystemPrompt()
throws OllamaBaseException, IOException, URISyntaxException, InterruptedException { throws OllamaBaseException, IOException, URISyntaxException, InterruptedException, ToolInvocationException {
api.pullModel(CHAT_MODEL_SYSTEM_PROMPT); api.pullModel(CHAT_MODEL_SYSTEM_PROMPT);
OllamaChatRequestBuilder builder = OllamaChatRequestBuilder.getInstance(CHAT_MODEL_SYSTEM_PROMPT); OllamaChatRequestBuilder builder = OllamaChatRequestBuilder.getInstance(CHAT_MODEL_SYSTEM_PROMPT);
OllamaChatRequest requestModel = builder.withMessage(OllamaChatMessageRole.SYSTEM, OllamaChatRequest requestModel = builder.withMessage(OllamaChatMessageRole.SYSTEM,
@ -318,7 +319,7 @@ public class OllamaAPIIntegrationTest {
@Test @Test
@Order(10) @Order(10)
void testChatWithImageFromURL() void testChatWithImageFromURL()
throws OllamaBaseException, IOException, InterruptedException, URISyntaxException { throws OllamaBaseException, IOException, InterruptedException, URISyntaxException, ToolInvocationException {
api.pullModel(IMAGE_MODEL_LLAVA); api.pullModel(IMAGE_MODEL_LLAVA);
OllamaChatRequestBuilder builder = OllamaChatRequestBuilder.getInstance(IMAGE_MODEL_LLAVA); OllamaChatRequestBuilder builder = OllamaChatRequestBuilder.getInstance(IMAGE_MODEL_LLAVA);
@ -336,7 +337,7 @@ public class OllamaAPIIntegrationTest {
@Test @Test
@Order(10) @Order(10)
void testChatWithImageFromFileWithHistoryRecognition() void testChatWithImageFromFileWithHistoryRecognition()
throws OllamaBaseException, IOException, URISyntaxException, InterruptedException { throws OllamaBaseException, IOException, URISyntaxException, InterruptedException, ToolInvocationException {
api.pullModel(IMAGE_MODEL_LLAVA); api.pullModel(IMAGE_MODEL_LLAVA);
OllamaChatRequestBuilder builder = OllamaChatRequestBuilder.getInstance(IMAGE_MODEL_LLAVA); OllamaChatRequestBuilder builder = OllamaChatRequestBuilder.getInstance(IMAGE_MODEL_LLAVA);
OllamaChatRequest requestModel = builder.withMessage(OllamaChatMessageRole.USER, OllamaChatRequest requestModel = builder.withMessage(OllamaChatMessageRole.USER,
@ -360,7 +361,7 @@ public class OllamaAPIIntegrationTest {
@Test @Test
@Order(11) @Order(11)
void testChatWithExplicitToolDefinition() void testChatWithExplicitToolDefinition()
throws OllamaBaseException, IOException, URISyntaxException, InterruptedException { throws OllamaBaseException, IOException, URISyntaxException, InterruptedException, ToolInvocationException {
api.pullModel(CHAT_MODEL_SYSTEM_PROMPT); api.pullModel(CHAT_MODEL_SYSTEM_PROMPT);
OllamaChatRequestBuilder builder = OllamaChatRequestBuilder.getInstance(CHAT_MODEL_SYSTEM_PROMPT); OllamaChatRequestBuilder builder = OllamaChatRequestBuilder.getInstance(CHAT_MODEL_SYSTEM_PROMPT);
@ -440,7 +441,7 @@ public class OllamaAPIIntegrationTest {
@Test @Test
@Order(12) @Order(12)
void testChatWithAnnotatedToolsAndSingleParam() void testChatWithAnnotatedToolsAndSingleParam()
throws OllamaBaseException, IOException, InterruptedException, URISyntaxException { throws OllamaBaseException, IOException, InterruptedException, URISyntaxException, ToolInvocationException {
api.pullModel(CHAT_MODEL_SYSTEM_PROMPT); api.pullModel(CHAT_MODEL_SYSTEM_PROMPT);
OllamaChatRequestBuilder builder = OllamaChatRequestBuilder.getInstance(CHAT_MODEL_SYSTEM_PROMPT); OllamaChatRequestBuilder builder = OllamaChatRequestBuilder.getInstance(CHAT_MODEL_SYSTEM_PROMPT);
@ -471,7 +472,7 @@ public class OllamaAPIIntegrationTest {
@Test @Test
@Order(13) @Order(13)
void testChatWithAnnotatedToolsAndMultipleParams() void testChatWithAnnotatedToolsAndMultipleParams()
throws OllamaBaseException, IOException, URISyntaxException, InterruptedException { throws OllamaBaseException, IOException, URISyntaxException, InterruptedException, ToolInvocationException {
api.pullModel(CHAT_MODEL_SYSTEM_PROMPT); api.pullModel(CHAT_MODEL_SYSTEM_PROMPT);
OllamaChatRequestBuilder builder = OllamaChatRequestBuilder.getInstance(CHAT_MODEL_SYSTEM_PROMPT); OllamaChatRequestBuilder builder = OllamaChatRequestBuilder.getInstance(CHAT_MODEL_SYSTEM_PROMPT);
@ -508,7 +509,7 @@ public class OllamaAPIIntegrationTest {
@Test @Test
@Order(14) @Order(14)
void testChatWithToolsAndStream() void testChatWithToolsAndStream()
throws OllamaBaseException, IOException, URISyntaxException, InterruptedException { throws OllamaBaseException, IOException, URISyntaxException, InterruptedException, ToolInvocationException {
api.pullModel(CHAT_MODEL_SYSTEM_PROMPT); api.pullModel(CHAT_MODEL_SYSTEM_PROMPT);
OllamaChatRequestBuilder builder = OllamaChatRequestBuilder.getInstance(CHAT_MODEL_SYSTEM_PROMPT); OllamaChatRequestBuilder builder = OllamaChatRequestBuilder.getInstance(CHAT_MODEL_SYSTEM_PROMPT);
final Tools.ToolSpecification databaseQueryToolSpecification = Tools.ToolSpecification.builder() final Tools.ToolSpecification databaseQueryToolSpecification = Tools.ToolSpecification.builder()
@ -585,7 +586,7 @@ public class OllamaAPIIntegrationTest {
@Test @Test
@Order(15) @Order(15)
void testChatWithStream() throws OllamaBaseException, IOException, URISyntaxException, InterruptedException { void testChatWithStream() throws OllamaBaseException, IOException, URISyntaxException, InterruptedException, ToolInvocationException {
api.pullModel(CHAT_MODEL_SYSTEM_PROMPT); api.pullModel(CHAT_MODEL_SYSTEM_PROMPT);
OllamaChatRequestBuilder builder = OllamaChatRequestBuilder.getInstance(CHAT_MODEL_SYSTEM_PROMPT); OllamaChatRequestBuilder builder = OllamaChatRequestBuilder.getInstance(CHAT_MODEL_SYSTEM_PROMPT);
OllamaChatRequest requestModel = builder.withMessage(OllamaChatMessageRole.USER, OllamaChatRequest requestModel = builder.withMessage(OllamaChatMessageRole.USER,