diff --git a/.github/workflows/run-tests.yml b/.github/workflows/run-tests.yml index e4f43e9..6432552 100644 --- a/.github/workflows/run-tests.yml +++ b/.github/workflows/run-tests.yml @@ -27,3 +27,6 @@ jobs: - name: Run unit tests run: mvn clean test -Punit-tests + + - name: Run integration tests + run: mvn clean verify -Pintegration-tests \ No newline at end of file diff --git a/pom.xml b/pom.xml index 2a5dfee..5226a68 100644 --- a/pom.xml +++ b/pom.xml @@ -216,6 +216,13 @@ 20240205 test + + + org.testcontainers + ollama + 1.20.2 + test + diff --git a/src/main/java/io/github/ollama4j/OllamaAPI.java b/src/main/java/io/github/ollama4j/OllamaAPI.java index 76af4c8..5d64044 100644 --- a/src/main/java/io/github/ollama4j/OllamaAPI.java +++ b/src/main/java/io/github/ollama4j/OllamaAPI.java @@ -323,26 +323,58 @@ public class OllamaAPI { public void pullModel(String modelName) throws OllamaBaseException, IOException, URISyntaxException, InterruptedException { String url = this.host + "/api/pull"; String jsonData = new ModelRequest(modelName).toString(); - HttpRequest request = getRequestBuilderDefault(new URI(url)).POST(HttpRequest.BodyPublishers.ofString(jsonData)).header("Accept", "application/json").header("Content-type", "application/json").build(); + HttpRequest request = getRequestBuilderDefault(new URI(url)) + .POST(HttpRequest.BodyPublishers.ofString(jsonData)) + .header("Accept", "application/json") + .header("Content-type", "application/json") + .build(); HttpClient client = HttpClient.newHttpClient(); HttpResponse response = client.send(request, HttpResponse.BodyHandlers.ofInputStream()); int statusCode = response.statusCode(); InputStream responseBodyStream = response.body(); String responseString = ""; + boolean success = false; // Flag to check the pull success. try (BufferedReader reader = new BufferedReader(new InputStreamReader(responseBodyStream, StandardCharsets.UTF_8))) { String line; while ((line = reader.readLine()) != null) { ModelPullResponse modelPullResponse = Utils.getObjectMapper().readValue(line, ModelPullResponse.class); - if (verbose) { - logger.info(modelPullResponse.getStatus()); + if (modelPullResponse != null && modelPullResponse.getStatus() != null) { + if (verbose) { + logger.info(modelName + ": " + modelPullResponse.getStatus()); + } + // Check if status is "success" and set success flag to true. + if ("success".equalsIgnoreCase(modelPullResponse.getStatus())) { + success = true; + } + } else { + logger.error("Received null or invalid status for model pull."); } } } + if (!success) { + logger.error("Model pull failed or returned invalid status."); + throw new OllamaBaseException("Model pull failed or returned invalid status."); + } if (statusCode != 200) { throw new OllamaBaseException(statusCode + " - " + responseString); } } + + public String getVersion() throws URISyntaxException, IOException, InterruptedException, OllamaBaseException { + String url = this.host + "/api/version"; + HttpClient httpClient = HttpClient.newHttpClient(); + HttpRequest httpRequest = getRequestBuilderDefault(new URI(url)).header("Accept", "application/json").header("Content-type", "application/json").GET().build(); + HttpResponse response = httpClient.send(httpRequest, HttpResponse.BodyHandlers.ofString()); + int statusCode = response.statusCode(); + String responseString = response.body(); + if (statusCode == 200) { + return Utils.getObjectMapper().readValue(responseString, OllamaVersion.class).getVersion(); + } else { + throw new OllamaBaseException(statusCode + " - " + responseString); + } + } + /** * Pulls a model using the specified Ollama library model tag. * The model is identified by a name and a tag, which are combined into a single identifier diff --git a/src/main/java/io/github/ollama4j/models/response/Model.java b/src/main/java/io/github/ollama4j/models/response/Model.java index e03049e..ae64f38 100644 --- a/src/main/java/io/github/ollama4j/models/response/Model.java +++ b/src/main/java/io/github/ollama4j/models/response/Model.java @@ -2,12 +2,14 @@ package io.github.ollama4j.models.response; import java.time.OffsetDateTime; +import com.fasterxml.jackson.annotation.JsonIgnoreProperties; import com.fasterxml.jackson.annotation.JsonProperty; import com.fasterxml.jackson.core.JsonProcessingException; import io.github.ollama4j.utils.Utils; import lombok.Data; @Data +@JsonIgnoreProperties(ignoreUnknown = true) public class Model { private String name; diff --git a/src/main/java/io/github/ollama4j/models/response/OllamaVersion.java b/src/main/java/io/github/ollama4j/models/response/OllamaVersion.java new file mode 100644 index 0000000..eac177b --- /dev/null +++ b/src/main/java/io/github/ollama4j/models/response/OllamaVersion.java @@ -0,0 +1,10 @@ +package io.github.ollama4j.models.response; + +import lombok.Data; + +import java.util.List; + +@Data +public class OllamaVersion { + private String version; +} diff --git a/src/test/java/io/github/ollama4j/integrationtests/TestAPIsTest.java b/src/test/java/io/github/ollama4j/integrationtests/TestAPIsTest.java new file mode 100644 index 0000000..d5553e5 --- /dev/null +++ b/src/test/java/io/github/ollama4j/integrationtests/TestAPIsTest.java @@ -0,0 +1,239 @@ +package io.github.ollama4j.integrationtests; + +import io.github.ollama4j.OllamaAPI; +import io.github.ollama4j.exceptions.OllamaBaseException; +import io.github.ollama4j.models.chat.OllamaChatMessageRole; +import io.github.ollama4j.models.chat.OllamaChatRequest; +import io.github.ollama4j.models.chat.OllamaChatRequestBuilder; +import io.github.ollama4j.models.chat.OllamaChatResult; +import io.github.ollama4j.models.embeddings.OllamaEmbedResponseModel; +import io.github.ollama4j.models.response.LibraryModel; +import io.github.ollama4j.models.response.Model; +import io.github.ollama4j.models.response.ModelDetail; +import io.github.ollama4j.models.response.OllamaResult; +import io.github.ollama4j.utils.OptionsBuilder; +import org.junit.jupiter.api.BeforeAll; +import org.junit.jupiter.api.Order; +import org.junit.jupiter.api.Test; +import org.testcontainers.ollama.OllamaContainer; + +import java.io.IOException; +import java.net.ConnectException; +import java.net.URISyntaxException; +import java.util.ArrayList; +import java.util.Arrays; +import java.util.List; + +import static org.junit.jupiter.api.Assertions.*; + +@SuppressWarnings("HttpUrlsUsage") +public class TestAPIsTest { + + private static OllamaContainer ollama; + private static OllamaAPI api; + + @BeforeAll + public static void setUp() { + String version = "0.5.13"; + int internalPort = 11434; + int mappedPort = 11435; + ollama = new OllamaContainer("ollama/ollama:" + version); + ollama.addExposedPort(internalPort); + List portBindings = new ArrayList<>(); + portBindings.add(mappedPort + ":" + internalPort); + ollama.setPortBindings(portBindings); + ollama.start(); + api = new OllamaAPI("http://" + ollama.getHost() + ":" + ollama.getMappedPort(internalPort)); + api.setRequestTimeoutSeconds(60); + } + + @Test + @Order(1) + void testWrongEndpoint() { + OllamaAPI ollamaAPI = new OllamaAPI("http://wrong-host:11434"); + assertThrows(ConnectException.class, ollamaAPI::listModels); + } + + @Test + @Order(1) + public void testVersionAPI() throws URISyntaxException, IOException, OllamaBaseException, InterruptedException { + String expectedVersion = ollama.getDockerImageName().split(":")[1]; + String actualVersion = api.getVersion(); + assertEquals(expectedVersion, actualVersion, "Version should match the Docker image version"); + } + + @Test + @Order(2) + public void testListModelsAPI() throws URISyntaxException, IOException, OllamaBaseException, InterruptedException { + // Fetch the list of models + List models = api.listModels(); + // Assert that the models list is not null + assertNotNull(models, "Models should not be null"); + // Assert that models list is either empty or contains more than 0 models + assertTrue(models.size() >= 0, "Models list should be empty or contain elements"); + } + + @Test + @Order(2) + void testListModelsFromLibrary() throws OllamaBaseException, IOException, URISyntaxException, InterruptedException { + List models = api.listModelsFromLibrary(); + assertNotNull(models); + assertFalse(models.isEmpty()); + } + + @Test + @Order(3) + public void testPullModelAPI() throws URISyntaxException, IOException, OllamaBaseException, InterruptedException { + api.pullModel("all-minilm"); + List models = api.listModels(); + assertNotNull(models, "Models should not be null"); + assertFalse(models.isEmpty(), "Models list should contain elements"); + } + + @Test + @Order(4) + void testListModelDetails() throws IOException, OllamaBaseException, URISyntaxException, InterruptedException { + String embeddingModelMinilm = "all-minilm"; + api.pullModel(embeddingModelMinilm); + ModelDetail modelDetails = api.getModelDetails("all-minilm"); + assertNotNull(modelDetails); + assertTrue(modelDetails.getModelFile().contains(embeddingModelMinilm)); + } + + @Test + @Order(5) + public void testGenerateEmbeddings() throws Exception { + String embeddingModelMinilm = "all-minilm"; + api.pullModel(embeddingModelMinilm); + OllamaEmbedResponseModel embeddings = api.embed(embeddingModelMinilm, Arrays.asList("Why is the sky blue?", "Why is the grass green?")); + assertNotNull(embeddings, "Embeddings should not be null"); + assertFalse(embeddings.getEmbeddings().isEmpty(), "Embeddings should not be empty"); + } + + @Test + @Order(6) + void testAskModelWithDefaultOptions() throws OllamaBaseException, IOException, InterruptedException, URISyntaxException { + String chatModel = "qwen2.5:0.5b"; + api.pullModel(chatModel); + OllamaResult result = + api.generate( + chatModel, + "What is the capital of France? And what's France's connection with Mona Lisa?", + false, + new OptionsBuilder().build()); + assertNotNull(result); + assertNotNull(result.getResponse()); + assertFalse(result.getResponse().isEmpty()); + } + + @Test + @Order(7) + void testAskModelWithDefaultOptionsStreamed() throws OllamaBaseException, IOException, URISyntaxException, InterruptedException { + String chatModel = "qwen2.5:0.5b"; + api.pullModel(chatModel); + StringBuffer sb = new StringBuffer(); + OllamaResult result = api.generate(chatModel, + "What is the capital of France? And what's France's connection with Mona Lisa?", + false, + new OptionsBuilder().build(), (s) -> { + System.out.println(s); + String substring = s.substring(sb.toString().length(), s.length()); + System.out.println(substring); + sb.append(substring); + }); + + assertNotNull(result); + assertNotNull(result.getResponse()); + assertFalse(result.getResponse().isEmpty()); + assertEquals(sb.toString().trim(), result.getResponse().trim()); + } + + @Test + @Order(8) + void testAskModelWithOptions() throws OllamaBaseException, IOException, URISyntaxException, InterruptedException { + String chatModel = "qwen2.5:0.5b-instruct"; + api.pullModel(chatModel); + + OllamaChatRequestBuilder builder = OllamaChatRequestBuilder.getInstance(chatModel); + OllamaChatRequest requestModel = builder.withMessage(OllamaChatMessageRole.SYSTEM, "You are a helpful assistant who can generate random person's first and last names in the format [First name, Last name].") + .build(); + requestModel = builder.withMessages(requestModel.getMessages()) + .withMessage(OllamaChatMessageRole.USER, "Give me a cool name") + .withOptions(new OptionsBuilder().setTemperature(0.5f).build()).build(); + OllamaChatResult chatResult = api.chat(requestModel); + + assertNotNull(chatResult); + assertNotNull(chatResult.getResponseModel()); + assertFalse(chatResult.getResponseModel().getMessage().getContent().isEmpty()); + } + + @Test + @Order(9) + void testChatWithSystemPrompt() throws OllamaBaseException, IOException, URISyntaxException, InterruptedException { + String chatModel = "llama3.2:1b"; + api.pullModel(chatModel); + OllamaChatRequestBuilder builder = OllamaChatRequestBuilder.getInstance(chatModel); + OllamaChatRequest requestModel = builder.withMessage(OllamaChatMessageRole.SYSTEM, + "You are a silent bot that only says 'Ssh'. Do not say anything else under any circumstances!") + .withMessage(OllamaChatMessageRole.USER, + "What's something that's brown and sticky?") + .withOptions(new OptionsBuilder().setTemperature(0.8f).build()) + .build(); + + OllamaChatResult chatResult = api.chat(requestModel); + assertNotNull(chatResult); + assertNotNull(chatResult.getResponseModel()); + assertNotNull(chatResult.getResponseModel().getMessage()); + assertFalse(chatResult.getResponseModel().getMessage().getContent().isBlank()); + assertTrue(chatResult.getResponseModel().getMessage().getContent().contains("Ssh")); + assertEquals(3, chatResult.getChatHistory().size()); + } + + @Test + @Order(10) + public void testChat() throws Exception { + String chatModel = "qwen2.5:0.5b"; + api.pullModel(chatModel); + OllamaChatRequestBuilder builder = OllamaChatRequestBuilder.getInstance(chatModel); + + // Create the initial user question + OllamaChatRequest requestModel = builder.withMessage(OllamaChatMessageRole.USER, "What is the capital of France?") + .build(); + + // Start conversation with model + OllamaChatResult chatResult = api.chat(requestModel); + + assertTrue( + chatResult.getChatHistory().stream() + .anyMatch(chat -> chat.getContent().contains("Paris")), + "Expected chat history to contain 'Paris'" + ); + + // Create the next user question: second largest city + requestModel = builder.withMessages(chatResult.getChatHistory()) + .withMessage(OllamaChatMessageRole.USER, "And what is its official language?") + .build(); + + // Continue conversation with model + chatResult = api.chat(requestModel); + + assertTrue( + chatResult.getChatHistory().stream() + .anyMatch(chat -> chat.getContent().contains("French")), + "Expected chat history to contain 'French'" + ); + + // Create the next user question: the third question + requestModel = builder.withMessages(chatResult.getChatHistory()) + .withMessage(OllamaChatMessageRole.USER, "What is the largest river in France?") + .build(); + + // Continue conversation with the model for the third question + chatResult = api.chat(requestModel); + + // verify the result + assertNotNull(chatResult, "Chat result should not be null"); + assertTrue(chatResult.getChatHistory().size() > 2, "Chat history should contain more than two messages"); + assertTrue(chatResult.getChatHistory().get(chatResult.getChatHistory().size() - 1).getContent().contains("river"), "Response should be related to river"); + } +} diff --git a/src/test/java/io/github/ollama4j/integrationtests/TestRealAPIs.java b/src/test/java/io/github/ollama4j/integrationtests/TestRealAPIs.java index a64fb70..c6fc1b2 100644 --- a/src/test/java/io/github/ollama4j/integrationtests/TestRealAPIs.java +++ b/src/test/java/io/github/ollama4j/integrationtests/TestRealAPIs.java @@ -1,622 +1,622 @@ -package io.github.ollama4j.integrationtests; - -import io.github.ollama4j.OllamaAPI; -import io.github.ollama4j.exceptions.OllamaBaseException; -import io.github.ollama4j.models.chat.*; -import io.github.ollama4j.models.response.ModelDetail; -import io.github.ollama4j.models.response.OllamaResult; -import io.github.ollama4j.models.embeddings.OllamaEmbeddingsRequestBuilder; -import io.github.ollama4j.models.embeddings.OllamaEmbeddingsRequestModel; -import io.github.ollama4j.samples.AnnotatedTool; -import io.github.ollama4j.tools.OllamaToolCallsFunction; -import io.github.ollama4j.tools.ToolFunction; -import io.github.ollama4j.tools.Tools; -import io.github.ollama4j.tools.annotations.OllamaToolService; -import io.github.ollama4j.utils.OptionsBuilder; -import lombok.Data; -import org.junit.jupiter.api.BeforeEach; -import org.junit.jupiter.api.Order; -import org.junit.jupiter.api.Test; -import org.slf4j.Logger; -import org.slf4j.LoggerFactory; - -import java.io.File; -import java.io.IOException; -import java.io.InputStream; -import java.net.ConnectException; -import java.net.URISyntaxException; -import java.net.http.HttpConnectTimeoutException; -import java.util.*; - -import static org.junit.jupiter.api.Assertions.*; - -@OllamaToolService(providers = {AnnotatedTool.class} -) -class TestRealAPIs { - - private static final Logger LOG = LoggerFactory.getLogger(TestRealAPIs.class); - - OllamaAPI ollamaAPI; - Config config; - - private File getImageFileFromClasspath(String fileName) { - ClassLoader classLoader = getClass().getClassLoader(); - return new File(Objects.requireNonNull(classLoader.getResource(fileName)).getFile()); - } - - @BeforeEach - void setUp() { - config = new Config(); - ollamaAPI = new OllamaAPI(config.getOllamaURL()); - ollamaAPI.setRequestTimeoutSeconds(config.getRequestTimeoutSeconds()); - ollamaAPI.setVerbose(true); - } - - @Test - @Order(1) - void testWrongEndpoint() { - OllamaAPI ollamaAPI = new OllamaAPI("http://wrong-host:11434"); - assertThrows(ConnectException.class, ollamaAPI::listModels); - } - - @Test - @Order(1) - void testEndpointReachability() { - try { - assertNotNull(ollamaAPI.listModels()); - } catch (HttpConnectTimeoutException e) { - fail(e.getMessage()); - } catch (Exception e) { - fail(e); - } - } - - @Test - @Order(2) - void testListModels() { - testEndpointReachability(); - try { - assertNotNull(ollamaAPI.listModels()); - ollamaAPI.listModels().forEach(System.out::println); - } catch (IOException | OllamaBaseException | InterruptedException | URISyntaxException e) { - fail(e); - } - } - - @Test - @Order(2) - void testListModelsFromLibrary() { - testEndpointReachability(); - try { - assertNotNull(ollamaAPI.listModelsFromLibrary()); - ollamaAPI.listModelsFromLibrary().forEach(System.out::println); - } catch (IOException | OllamaBaseException | InterruptedException | URISyntaxException e) { - fail(e); - } - } - - @Test - @Order(2) - void testPullModel() { - testEndpointReachability(); - try { - ollamaAPI.pullModel(config.getModel()); - boolean found = - ollamaAPI.listModels().stream() - .anyMatch(model -> model.getModel().equalsIgnoreCase(config.getModel())); - assertTrue(found); - } catch (IOException | OllamaBaseException | InterruptedException | URISyntaxException e) { - fail(e); - } - } - - @Test - @Order(3) - void testListDtails() { - testEndpointReachability(); - try { - ModelDetail modelDetails = ollamaAPI.getModelDetails(config.getModel()); - assertNotNull(modelDetails); - System.out.println(modelDetails); - } catch (IOException | OllamaBaseException | InterruptedException | URISyntaxException e) { - fail(e); - } - } - - @Test - @Order(3) - void testAskModelWithDefaultOptions() { - testEndpointReachability(); - try { - OllamaResult result = - ollamaAPI.generate( - config.getModel(), - "What is the capital of France? And what's France's connection with Mona Lisa?", - false, - new OptionsBuilder().build()); - assertNotNull(result); - assertNotNull(result.getResponse()); - assertFalse(result.getResponse().isEmpty()); - } catch (IOException | OllamaBaseException | InterruptedException e) { - fail(e); - } - } - - @Test - @Order(3) - void testAskModelWithDefaultOptionsStreamed() { - testEndpointReachability(); - try { - StringBuffer sb = new StringBuffer(""); - OllamaResult result = ollamaAPI.generate(config.getModel(), - "What is the capital of France? And what's France's connection with Mona Lisa?", - false, - new OptionsBuilder().build(), (s) -> { - LOG.info(s); - String substring = s.substring(sb.toString().length(), s.length()); - LOG.info(substring); - sb.append(substring); - }); - - assertNotNull(result); - assertNotNull(result.getResponse()); - assertFalse(result.getResponse().isEmpty()); - assertEquals(sb.toString().trim(), result.getResponse().trim()); - } catch (IOException | OllamaBaseException | InterruptedException e) { - fail(e); - } - } - - @Test - @Order(3) - void testAskModelWithOptions() { - testEndpointReachability(); - try { - OllamaResult result = - ollamaAPI.generate( - config.getModel(), - "What is the capital of France? And what's France's connection with Mona Lisa?", - true, - new OptionsBuilder().setTemperature(0.9f).build()); - assertNotNull(result); - assertNotNull(result.getResponse()); - assertFalse(result.getResponse().isEmpty()); - } catch (IOException | OllamaBaseException | InterruptedException e) { - fail(e); - } - } - - @Test - @Order(3) - void testChat() { - testEndpointReachability(); - try { - OllamaChatRequestBuilder builder = OllamaChatRequestBuilder.getInstance(config.getModel()); - OllamaChatRequest requestModel = builder.withMessage(OllamaChatMessageRole.USER, "What is the capital of France?") - .withMessage(OllamaChatMessageRole.ASSISTANT, "Should be Paris!") - .withMessage(OllamaChatMessageRole.USER, "And what is the second larges city?") - .build(); - - OllamaChatResult chatResult = ollamaAPI.chat(requestModel); - assertNotNull(chatResult); - assertNotNull(chatResult.getResponseModel()); - assertNotNull(chatResult.getResponseModel().getMessage()); - assertFalse(chatResult.getResponseModel().getMessage().getContent().isBlank()); - assertEquals(4, chatResult.getChatHistory().size()); - } catch (IOException | OllamaBaseException | InterruptedException e) { - fail(e); - } - } - - @Test - @Order(3) - void testChatWithSystemPrompt() { - testEndpointReachability(); - try { - OllamaChatRequestBuilder builder = OllamaChatRequestBuilder.getInstance(config.getModel()); - OllamaChatRequest requestModel = builder.withMessage(OllamaChatMessageRole.SYSTEM, - "You are a silent bot that only says 'NI'. Do not say anything else under any circumstances!") - .withMessage(OllamaChatMessageRole.USER, - "What is the capital of France? And what's France's connection with Mona Lisa?") - .build(); - - OllamaChatResult chatResult = ollamaAPI.chat(requestModel); - assertNotNull(chatResult); - assertNotNull(chatResult.getResponseModel()); - assertNotNull(chatResult.getResponseModel().getMessage()); - assertFalse(chatResult.getResponseModel().getMessage().getContent().isBlank()); - assertTrue(chatResult.getResponseModel().getMessage().getContent().startsWith("NI")); - assertEquals(3, chatResult.getChatHistory().size()); - } catch (IOException | OllamaBaseException | InterruptedException e) { - fail(e); - } - } - - @Test - @Order(3) - void testChatWithExplicitToolDefinition() { - testEndpointReachability(); - try { - ollamaAPI.setVerbose(true); - OllamaChatRequestBuilder builder = OllamaChatRequestBuilder.getInstance(config.getModel()); - - final Tools.ToolSpecification databaseQueryToolSpecification = Tools.ToolSpecification.builder() - .functionName("get-employee-details") - .functionDescription("Get employee details from the database") - .toolPrompt( - Tools.PromptFuncDefinition.builder().type("function").function( - Tools.PromptFuncDefinition.PromptFuncSpec.builder() - .name("get-employee-details") - .description("Get employee details from the database") - .parameters( - Tools.PromptFuncDefinition.Parameters.builder() - .type("object") - .properties( - new Tools.PropsBuilder() - .withProperty("employee-name", Tools.PromptFuncDefinition.Property.builder().type("string").description("The name of the employee, e.g. John Doe").required(true).build()) - .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()) - .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()) - .build() - ) - .required(List.of("employee-name")) - .build() - ).build() - ).build() - ) - .toolFunction(new DBQueryFunction()) - .build(); - - ollamaAPI.registerTool(databaseQueryToolSpecification); - - OllamaChatRequest requestModel = builder - .withMessage(OllamaChatMessageRole.USER, - "Give me the ID of the employee named 'Rahul Kumar'?") - .build(); - - OllamaChatResult chatResult = ollamaAPI.chat(requestModel); - assertNotNull(chatResult); - assertNotNull(chatResult.getResponseModel()); - assertNotNull(chatResult.getResponseModel().getMessage()); - assertEquals(OllamaChatMessageRole.ASSISTANT.getRoleName(),chatResult.getResponseModel().getMessage().getRole().getRoleName()); - List toolCalls = chatResult.getChatHistory().get(1).getToolCalls(); - assertEquals(1, toolCalls.size()); - OllamaToolCallsFunction function = toolCalls.get(0).getFunction(); - assertEquals("get-employee-details", function.getName()); - assertEquals(1, function.getArguments().size()); - Object employeeName = function.getArguments().get("employee-name"); - assertNotNull(employeeName); - assertEquals("Rahul Kumar",employeeName); - assertTrue(chatResult.getChatHistory().size()>2); - List finalToolCalls = chatResult.getResponseModel().getMessage().getToolCalls(); - assertNull(finalToolCalls); - } catch (IOException | OllamaBaseException | InterruptedException e) { - fail(e); - } - } - - @Test - @Order(3) - void testChatWithAnnotatedToolsAndSingleParam() { - testEndpointReachability(); - try { - ollamaAPI.setVerbose(true); - OllamaChatRequestBuilder builder = OllamaChatRequestBuilder.getInstance(config.getModel()); - - ollamaAPI.registerAnnotatedTools(); - - OllamaChatRequest requestModel = builder - .withMessage(OllamaChatMessageRole.USER, - "Compute the most important constant in the world using 5 digits") - .build(); - - OllamaChatResult chatResult = ollamaAPI.chat(requestModel); - assertNotNull(chatResult); - assertNotNull(chatResult.getResponseModel()); - assertNotNull(chatResult.getResponseModel().getMessage()); - assertEquals(OllamaChatMessageRole.ASSISTANT.getRoleName(),chatResult.getResponseModel().getMessage().getRole().getRoleName()); - List toolCalls = chatResult.getChatHistory().get(1).getToolCalls(); - assertEquals(1, toolCalls.size()); - OllamaToolCallsFunction function = toolCalls.get(0).getFunction(); - assertEquals("computeImportantConstant", function.getName()); - assertEquals(1, function.getArguments().size()); - Object noOfDigits = function.getArguments().get("noOfDigits"); - assertNotNull(noOfDigits); - assertEquals("5", noOfDigits.toString()); - assertTrue(chatResult.getChatHistory().size()>2); - List finalToolCalls = chatResult.getResponseModel().getMessage().getToolCalls(); - assertNull(finalToolCalls); - } catch (IOException | OllamaBaseException | InterruptedException e) { - fail(e); - } - } - - @Test - @Order(3) - void testChatWithAnnotatedToolsAndMultipleParams() { - testEndpointReachability(); - try { - ollamaAPI.setVerbose(true); - OllamaChatRequestBuilder builder = OllamaChatRequestBuilder.getInstance(config.getModel()); - - ollamaAPI.registerAnnotatedTools(new AnnotatedTool()); - - OllamaChatRequest requestModel = builder - .withMessage(OllamaChatMessageRole.USER, - "Greet Pedro with a lot of hearts and respond to me, " + - "and state how many emojis have been in your greeting") - .build(); - - OllamaChatResult chatResult = ollamaAPI.chat(requestModel); - assertNotNull(chatResult); - assertNotNull(chatResult.getResponseModel()); - assertNotNull(chatResult.getResponseModel().getMessage()); - assertEquals(OllamaChatMessageRole.ASSISTANT.getRoleName(),chatResult.getResponseModel().getMessage().getRole().getRoleName()); - List toolCalls = chatResult.getChatHistory().get(1).getToolCalls(); - assertEquals(1, toolCalls.size()); - OllamaToolCallsFunction function = toolCalls.get(0).getFunction(); - assertEquals("sayHello", function.getName()); - assertEquals(2, function.getArguments().size()); - Object name = function.getArguments().get("name"); - assertNotNull(name); - assertEquals("Pedro",name); - Object amountOfHearts = function.getArguments().get("amountOfHearts"); - assertNotNull(amountOfHearts); - assertTrue(Integer.parseInt(amountOfHearts.toString()) > 1); - assertTrue(chatResult.getChatHistory().size()>2); - List finalToolCalls = chatResult.getResponseModel().getMessage().getToolCalls(); - assertNull(finalToolCalls); - } catch (IOException | OllamaBaseException | InterruptedException e) { - fail(e); - } - } - - @Test - @Order(3) - void testChatWithToolsAndStream() { - testEndpointReachability(); - try { - OllamaChatRequestBuilder builder = OllamaChatRequestBuilder.getInstance(config.getModel()); - final Tools.ToolSpecification databaseQueryToolSpecification = Tools.ToolSpecification.builder() - .functionName("get-employee-details") - .functionDescription("Get employee details from the database") - .toolPrompt( - Tools.PromptFuncDefinition.builder().type("function").function( - Tools.PromptFuncDefinition.PromptFuncSpec.builder() - .name("get-employee-details") - .description("Get employee details from the database") - .parameters( - Tools.PromptFuncDefinition.Parameters.builder() - .type("object") - .properties( - new Tools.PropsBuilder() - .withProperty("employee-name", Tools.PromptFuncDefinition.Property.builder().type("string").description("The name of the employee, e.g. John Doe").required(true).build()) - .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()) - .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()) - .build() - ) - .required(List.of("employee-name")) - .build() - ).build() - ).build() - ) - .toolFunction(new DBQueryFunction()) - .build(); - - ollamaAPI.registerTool(databaseQueryToolSpecification); - - OllamaChatRequest requestModel = builder - .withMessage(OllamaChatMessageRole.USER, - "Give me the ID of the employee named 'Rahul Kumar'?") - .build(); - - StringBuffer sb = new StringBuffer(); - - OllamaChatResult chatResult = ollamaAPI.chat(requestModel, (s) -> { - LOG.info(s); - String substring = s.substring(sb.toString().length()); - LOG.info(substring); - sb.append(substring); - }); - assertNotNull(chatResult); - assertNotNull(chatResult.getResponseModel()); - assertNotNull(chatResult.getResponseModel().getMessage()); - assertNotNull(chatResult.getResponseModel().getMessage().getContent()); - assertEquals(sb.toString().trim(), chatResult.getResponseModel().getMessage().getContent().trim()); - } catch (IOException | OllamaBaseException | InterruptedException e) { - fail(e); - } - } - - @Test - @Order(3) - void testChatWithStream() { - testEndpointReachability(); - try { - OllamaChatRequestBuilder builder = OllamaChatRequestBuilder.getInstance(config.getModel()); - OllamaChatRequest requestModel = builder.withMessage(OllamaChatMessageRole.USER, - "What is the capital of France? And what's France's connection with Mona Lisa?") - .build(); - - StringBuffer sb = new StringBuffer(""); - - OllamaChatResult chatResult = ollamaAPI.chat(requestModel, (s) -> { - LOG.info(s); - String substring = s.substring(sb.toString().length(), s.length()); - LOG.info(substring); - sb.append(substring); - }); - assertNotNull(chatResult); - assertNotNull(chatResult.getResponseModel()); - assertNotNull(chatResult.getResponseModel().getMessage()); - assertNotNull(chatResult.getResponseModel().getMessage().getContent()); - assertEquals(sb.toString().trim(), chatResult.getResponseModel().getMessage().getContent().trim()); - } catch (IOException | OllamaBaseException | InterruptedException e) { - fail(e); - } - } - - @Test - @Order(3) - void testChatWithImageFromFileWithHistoryRecognition() { - testEndpointReachability(); - try { - OllamaChatRequestBuilder builder = - OllamaChatRequestBuilder.getInstance(config.getImageModel()); - OllamaChatRequest requestModel = - builder.withMessage(OllamaChatMessageRole.USER, "What's in the picture?",Collections.emptyList(), - List.of(getImageFileFromClasspath("dog-on-a-boat.jpg"))).build(); - - OllamaChatResult chatResult = ollamaAPI.chat(requestModel); - assertNotNull(chatResult); - assertNotNull(chatResult.getResponseModel()); - - builder.reset(); - - requestModel = - builder.withMessages(chatResult.getChatHistory()) - .withMessage(OllamaChatMessageRole.USER, "What's the dogs breed?").build(); - - chatResult = ollamaAPI.chat(requestModel); - assertNotNull(chatResult); - assertNotNull(chatResult.getResponseModel()); - - - } catch (IOException | OllamaBaseException | InterruptedException e) { - fail(e); - } - } - - @Test - @Order(3) - void testChatWithImageFromURL() { - testEndpointReachability(); - try { - OllamaChatRequestBuilder builder = OllamaChatRequestBuilder.getInstance(config.getImageModel()); - OllamaChatRequest requestModel = builder.withMessage(OllamaChatMessageRole.USER, "What's in the picture?",Collections.emptyList(), - "https://t3.ftcdn.net/jpg/02/96/63/80/360_F_296638053_0gUVA4WVBKceGsIr7LNqRWSnkusi07dq.jpg") - .build(); - - OllamaChatResult chatResult = ollamaAPI.chat(requestModel); - assertNotNull(chatResult); - } catch (IOException | OllamaBaseException | InterruptedException e) { - fail(e); - } - } - - @Test - @Order(3) - void testAskModelWithOptionsAndImageFiles() { - testEndpointReachability(); - File imageFile = getImageFileFromClasspath("dog-on-a-boat.jpg"); - try { - OllamaResult result = - ollamaAPI.generateWithImageFiles( - config.getImageModel(), - "What is in this image?", - List.of(imageFile), - new OptionsBuilder().build()); - assertNotNull(result); - assertNotNull(result.getResponse()); - assertFalse(result.getResponse().isEmpty()); - } catch (IOException | OllamaBaseException | InterruptedException e) { - fail(e); - } - } - - @Test - @Order(3) - void testAskModelWithOptionsAndImageFilesStreamed() { - testEndpointReachability(); - File imageFile = getImageFileFromClasspath("dog-on-a-boat.jpg"); - try { - StringBuffer sb = new StringBuffer(""); - - OllamaResult result = ollamaAPI.generateWithImageFiles(config.getImageModel(), - "What is in this image?", List.of(imageFile), new OptionsBuilder().build(), (s) -> { - LOG.info(s); - String substring = s.substring(sb.toString().length(), s.length()); - LOG.info(substring); - sb.append(substring); - }); - assertNotNull(result); - assertNotNull(result.getResponse()); - assertFalse(result.getResponse().isEmpty()); - assertEquals(sb.toString().trim(), result.getResponse().trim()); - } catch (IOException | OllamaBaseException | InterruptedException e) { - fail(e); - } - } - - @Test - @Order(3) - void testAskModelWithOptionsAndImageURLs() { - testEndpointReachability(); - try { - OllamaResult result = - ollamaAPI.generateWithImageURLs( - config.getImageModel(), - "What is in this image?", - List.of( - "https://t3.ftcdn.net/jpg/02/96/63/80/360_F_296638053_0gUVA4WVBKceGsIr7LNqRWSnkusi07dq.jpg"), - new OptionsBuilder().build()); - assertNotNull(result); - assertNotNull(result.getResponse()); - assertFalse(result.getResponse().isEmpty()); - } catch (IOException | OllamaBaseException | InterruptedException | URISyntaxException e) { - fail(e); - } - } - - @Test - @Order(3) - public void testEmbedding() { - testEndpointReachability(); - try { - OllamaEmbeddingsRequestModel request = OllamaEmbeddingsRequestBuilder - .getInstance(config.getModel(), "What is the capital of France?").build(); - - List embeddings = ollamaAPI.generateEmbeddings(request); - - assertNotNull(embeddings); - assertFalse(embeddings.isEmpty()); - } catch (IOException | OllamaBaseException | InterruptedException e) { - fail(e); - } - } -} - -class DBQueryFunction implements ToolFunction { - @Override - public Object apply(Map arguments) { - // perform DB operations here - return String.format("Employee Details {ID: %s, Name: %s, Address: %s, Phone: %s}", UUID.randomUUID(), arguments.get("employee-name"), arguments.get("employee-address"), arguments.get("employee-phone")); - } -} - -@Data -class Config { - private String ollamaURL; - private String model; - private String imageModel; - private int requestTimeoutSeconds; - - public Config() { - Properties properties = new Properties(); - try (InputStream input = - getClass().getClassLoader().getResourceAsStream("test-config.properties")) { - if (input == null) { - throw new RuntimeException("Sorry, unable to find test-config.properties"); - } - properties.load(input); - this.ollamaURL = properties.getProperty("ollama.url"); - this.model = properties.getProperty("ollama.model"); - this.imageModel = properties.getProperty("ollama.model.image"); - this.requestTimeoutSeconds = - Integer.parseInt(properties.getProperty("ollama.request-timeout-seconds")); - } catch (IOException e) { - throw new RuntimeException("Error loading properties", e); - } - } - - -} +//package io.github.ollama4j.integrationtests; +// +//import io.github.ollama4j.OllamaAPI; +//import io.github.ollama4j.exceptions.OllamaBaseException; +//import io.github.ollama4j.models.chat.*; +//import io.github.ollama4j.models.response.ModelDetail; +//import io.github.ollama4j.models.response.OllamaResult; +//import io.github.ollama4j.models.embeddings.OllamaEmbeddingsRequestBuilder; +//import io.github.ollama4j.models.embeddings.OllamaEmbeddingsRequestModel; +//import io.github.ollama4j.samples.AnnotatedTool; +//import io.github.ollama4j.tools.OllamaToolCallsFunction; +//import io.github.ollama4j.tools.ToolFunction; +//import io.github.ollama4j.tools.Tools; +//import io.github.ollama4j.tools.annotations.OllamaToolService; +//import io.github.ollama4j.utils.OptionsBuilder; +//import lombok.Data; +//import org.junit.jupiter.api.BeforeEach; +//import org.junit.jupiter.api.Order; +//import org.junit.jupiter.api.Test; +//import org.slf4j.Logger; +//import org.slf4j.LoggerFactory; +// +//import java.io.File; +//import java.io.IOException; +//import java.io.InputStream; +//import java.net.ConnectException; +//import java.net.URISyntaxException; +//import java.net.http.HttpConnectTimeoutException; +//import java.util.*; +// +//import static org.junit.jupiter.api.Assertions.*; +// +//@OllamaToolService(providers = {AnnotatedTool.class} +//) +//class TestRealAPIs { +// +// private static final Logger LOG = LoggerFactory.getLogger(TestRealAPIs.class); +// +// OllamaAPI ollamaAPI; +// Config config; +// +// private File getImageFileFromClasspath(String fileName) { +// ClassLoader classLoader = getClass().getClassLoader(); +// return new File(Objects.requireNonNull(classLoader.getResource(fileName)).getFile()); +// } +// +// @BeforeEach +// void setUp() { +// config = new Config(); +// ollamaAPI = new OllamaAPI(config.getOllamaURL()); +// ollamaAPI.setRequestTimeoutSeconds(config.getRequestTimeoutSeconds()); +// ollamaAPI.setVerbose(true); +// } +// +// @Test +// @Order(1) +// void testWrongEndpoint() { +// OllamaAPI ollamaAPI = new OllamaAPI("http://wrong-host:11434"); +// assertThrows(ConnectException.class, ollamaAPI::listModels); +// } +// +// @Test +// @Order(1) +// void testEndpointReachability() { +// try { +// assertNotNull(ollamaAPI.listModels()); +// } catch (HttpConnectTimeoutException e) { +// fail(e.getMessage()); +// } catch (Exception e) { +// fail(e); +// } +// } +// +//// @Test +//// @Order(2) +//// void testListModels() { +//// testEndpointReachability(); +//// try { +//// assertNotNull(ollamaAPI.listModels()); +//// ollamaAPI.listModels().forEach(System.out::println); +//// } catch (IOException | OllamaBaseException | InterruptedException | URISyntaxException e) { +//// fail(e); +//// } +//// } +//// +//// @Test +//// @Order(2) +//// void testListModelsFromLibrary() { +//// testEndpointReachability(); +//// try { +//// assertNotNull(ollamaAPI.listModelsFromLibrary()); +//// ollamaAPI.listModelsFromLibrary().forEach(System.out::println); +//// } catch (IOException | OllamaBaseException | InterruptedException | URISyntaxException e) { +//// fail(e); +//// } +//// } +//// +//// @Test +//// @Order(2) +//// void testPullModel() { +//// testEndpointReachability(); +//// try { +//// ollamaAPI.pullModel(config.getModel()); +//// boolean found = +//// ollamaAPI.listModels().stream() +//// .anyMatch(model -> model.getModel().equalsIgnoreCase(config.getModel())); +//// assertTrue(found); +//// } catch (IOException | OllamaBaseException | InterruptedException | URISyntaxException e) { +//// fail(e); +//// } +//// } +//// +//// @Test +//// @Order(3) +//// void testListDtails() { +//// testEndpointReachability(); +//// try { +//// ModelDetail modelDetails = ollamaAPI.getModelDetails(config.getModel()); +//// assertNotNull(modelDetails); +//// System.out.println(modelDetails); +//// } catch (IOException | OllamaBaseException | InterruptedException | URISyntaxException e) { +//// fail(e); +//// } +//// } +//// +//// @Test +//// @Order(3) +//// void testAskModelWithDefaultOptions() { +//// testEndpointReachability(); +//// try { +//// OllamaResult result = +//// ollamaAPI.generate( +//// config.getModel(), +//// "What is the capital of France? And what's France's connection with Mona Lisa?", +//// false, +//// new OptionsBuilder().build()); +//// assertNotNull(result); +//// assertNotNull(result.getResponse()); +//// assertFalse(result.getResponse().isEmpty()); +//// } catch (IOException | OllamaBaseException | InterruptedException e) { +//// fail(e); +//// } +//// } +//// +//// @Test +//// @Order(3) +//// void testAskModelWithDefaultOptionsStreamed() { +//// testEndpointReachability(); +//// try { +//// StringBuffer sb = new StringBuffer(""); +//// OllamaResult result = ollamaAPI.generate(config.getModel(), +//// "What is the capital of France? And what's France's connection with Mona Lisa?", +//// false, +//// new OptionsBuilder().build(), (s) -> { +//// LOG.info(s); +//// String substring = s.substring(sb.toString().length(), s.length()); +//// LOG.info(substring); +//// sb.append(substring); +//// }); +//// +//// assertNotNull(result); +//// assertNotNull(result.getResponse()); +//// assertFalse(result.getResponse().isEmpty()); +//// assertEquals(sb.toString().trim(), result.getResponse().trim()); +//// } catch (IOException | OllamaBaseException | InterruptedException e) { +//// fail(e); +//// } +//// } +//// +//// @Test +//// @Order(3) +//// void testAskModelWithOptions() { +//// testEndpointReachability(); +//// try { +//// OllamaResult result = +//// ollamaAPI.generate( +//// config.getModel(), +//// "What is the capital of France? And what's France's connection with Mona Lisa?", +//// true, +//// new OptionsBuilder().setTemperature(0.9f).build()); +//// assertNotNull(result); +//// assertNotNull(result.getResponse()); +//// assertFalse(result.getResponse().isEmpty()); +//// } catch (IOException | OllamaBaseException | InterruptedException e) { +//// fail(e); +//// } +//// } +//// +//// @Test +//// @Order(3) +//// void testChat() { +//// testEndpointReachability(); +//// try { +//// OllamaChatRequestBuilder builder = OllamaChatRequestBuilder.getInstance(config.getModel()); +//// OllamaChatRequest requestModel = builder.withMessage(OllamaChatMessageRole.USER, "What is the capital of France?") +//// .withMessage(OllamaChatMessageRole.ASSISTANT, "Should be Paris!") +//// .withMessage(OllamaChatMessageRole.USER, "And what is the second larges city?") +//// .build(); +//// +//// OllamaChatResult chatResult = ollamaAPI.chat(requestModel); +//// assertNotNull(chatResult); +//// assertNotNull(chatResult.getResponseModel()); +//// assertNotNull(chatResult.getResponseModel().getMessage()); +//// assertFalse(chatResult.getResponseModel().getMessage().getContent().isBlank()); +//// assertEquals(4, chatResult.getChatHistory().size()); +//// } catch (IOException | OllamaBaseException | InterruptedException e) { +//// fail(e); +//// } +//// } +//// +//// @Test +//// @Order(3) +//// void testChatWithSystemPrompt() { +//// testEndpointReachability(); +//// try { +//// OllamaChatRequestBuilder builder = OllamaChatRequestBuilder.getInstance(config.getModel()); +//// OllamaChatRequest requestModel = builder.withMessage(OllamaChatMessageRole.SYSTEM, +//// "You are a silent bot that only says 'NI'. Do not say anything else under any circumstances!") +//// .withMessage(OllamaChatMessageRole.USER, +//// "What is the capital of France? And what's France's connection with Mona Lisa?") +//// .build(); +//// +//// OllamaChatResult chatResult = ollamaAPI.chat(requestModel); +//// assertNotNull(chatResult); +//// assertNotNull(chatResult.getResponseModel()); +//// assertNotNull(chatResult.getResponseModel().getMessage()); +//// assertFalse(chatResult.getResponseModel().getMessage().getContent().isBlank()); +//// assertTrue(chatResult.getResponseModel().getMessage().getContent().startsWith("NI")); +//// assertEquals(3, chatResult.getChatHistory().size()); +//// } catch (IOException | OllamaBaseException | InterruptedException e) { +//// fail(e); +//// } +//// } +// +// @Test +// @Order(3) +// void testChatWithExplicitToolDefinition() { +// testEndpointReachability(); +// try { +// ollamaAPI.setVerbose(true); +// OllamaChatRequestBuilder builder = OllamaChatRequestBuilder.getInstance(config.getModel()); +// +// final Tools.ToolSpecification databaseQueryToolSpecification = Tools.ToolSpecification.builder() +// .functionName("get-employee-details") +// .functionDescription("Get employee details from the database") +// .toolPrompt( +// Tools.PromptFuncDefinition.builder().type("function").function( +// Tools.PromptFuncDefinition.PromptFuncSpec.builder() +// .name("get-employee-details") +// .description("Get employee details from the database") +// .parameters( +// Tools.PromptFuncDefinition.Parameters.builder() +// .type("object") +// .properties( +// new Tools.PropsBuilder() +// .withProperty("employee-name", Tools.PromptFuncDefinition.Property.builder().type("string").description("The name of the employee, e.g. John Doe").required(true).build()) +// .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()) +// .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()) +// .build() +// ) +// .required(List.of("employee-name")) +// .build() +// ).build() +// ).build() +// ) +// .toolFunction(new DBQueryFunction()) +// .build(); +// +// ollamaAPI.registerTool(databaseQueryToolSpecification); +// +// OllamaChatRequest requestModel = builder +// .withMessage(OllamaChatMessageRole.USER, +// "Give me the ID of the employee named 'Rahul Kumar'?") +// .build(); +// +// OllamaChatResult chatResult = ollamaAPI.chat(requestModel); +// assertNotNull(chatResult); +// assertNotNull(chatResult.getResponseModel()); +// assertNotNull(chatResult.getResponseModel().getMessage()); +// assertEquals(OllamaChatMessageRole.ASSISTANT.getRoleName(),chatResult.getResponseModel().getMessage().getRole().getRoleName()); +// List toolCalls = chatResult.getChatHistory().get(1).getToolCalls(); +// assertEquals(1, toolCalls.size()); +// OllamaToolCallsFunction function = toolCalls.get(0).getFunction(); +// assertEquals("get-employee-details", function.getName()); +// assertEquals(1, function.getArguments().size()); +// Object employeeName = function.getArguments().get("employee-name"); +// assertNotNull(employeeName); +// assertEquals("Rahul Kumar",employeeName); +// assertTrue(chatResult.getChatHistory().size()>2); +// List finalToolCalls = chatResult.getResponseModel().getMessage().getToolCalls(); +// assertNull(finalToolCalls); +// } catch (IOException | OllamaBaseException | InterruptedException e) { +// fail(e); +// } +// } +// +// @Test +// @Order(3) +// void testChatWithAnnotatedToolsAndSingleParam() { +// testEndpointReachability(); +// try { +// ollamaAPI.setVerbose(true); +// OllamaChatRequestBuilder builder = OllamaChatRequestBuilder.getInstance(config.getModel()); +// +// ollamaAPI.registerAnnotatedTools(); +// +// OllamaChatRequest requestModel = builder +// .withMessage(OllamaChatMessageRole.USER, +// "Compute the most important constant in the world using 5 digits") +// .build(); +// +// OllamaChatResult chatResult = ollamaAPI.chat(requestModel); +// assertNotNull(chatResult); +// assertNotNull(chatResult.getResponseModel()); +// assertNotNull(chatResult.getResponseModel().getMessage()); +// assertEquals(OllamaChatMessageRole.ASSISTANT.getRoleName(),chatResult.getResponseModel().getMessage().getRole().getRoleName()); +// List toolCalls = chatResult.getChatHistory().get(1).getToolCalls(); +// assertEquals(1, toolCalls.size()); +// OllamaToolCallsFunction function = toolCalls.get(0).getFunction(); +// assertEquals("computeImportantConstant", function.getName()); +// assertEquals(1, function.getArguments().size()); +// Object noOfDigits = function.getArguments().get("noOfDigits"); +// assertNotNull(noOfDigits); +// assertEquals("5", noOfDigits.toString()); +// assertTrue(chatResult.getChatHistory().size()>2); +// List finalToolCalls = chatResult.getResponseModel().getMessage().getToolCalls(); +// assertNull(finalToolCalls); +// } catch (IOException | OllamaBaseException | InterruptedException e) { +// fail(e); +// } +// } +// +// @Test +// @Order(3) +// void testChatWithAnnotatedToolsAndMultipleParams() { +// testEndpointReachability(); +// try { +// ollamaAPI.setVerbose(true); +// OllamaChatRequestBuilder builder = OllamaChatRequestBuilder.getInstance(config.getModel()); +// +// ollamaAPI.registerAnnotatedTools(new AnnotatedTool()); +// +// OllamaChatRequest requestModel = builder +// .withMessage(OllamaChatMessageRole.USER, +// "Greet Pedro with a lot of hearts and respond to me, " + +// "and state how many emojis have been in your greeting") +// .build(); +// +// OllamaChatResult chatResult = ollamaAPI.chat(requestModel); +// assertNotNull(chatResult); +// assertNotNull(chatResult.getResponseModel()); +// assertNotNull(chatResult.getResponseModel().getMessage()); +// assertEquals(OllamaChatMessageRole.ASSISTANT.getRoleName(),chatResult.getResponseModel().getMessage().getRole().getRoleName()); +// List toolCalls = chatResult.getChatHistory().get(1).getToolCalls(); +// assertEquals(1, toolCalls.size()); +// OllamaToolCallsFunction function = toolCalls.get(0).getFunction(); +// assertEquals("sayHello", function.getName()); +// assertEquals(2, function.getArguments().size()); +// Object name = function.getArguments().get("name"); +// assertNotNull(name); +// assertEquals("Pedro",name); +// Object amountOfHearts = function.getArguments().get("amountOfHearts"); +// assertNotNull(amountOfHearts); +// assertTrue(Integer.parseInt(amountOfHearts.toString()) > 1); +// assertTrue(chatResult.getChatHistory().size()>2); +// List finalToolCalls = chatResult.getResponseModel().getMessage().getToolCalls(); +// assertNull(finalToolCalls); +// } catch (IOException | OllamaBaseException | InterruptedException e) { +// fail(e); +// } +// } +// +// @Test +// @Order(3) +// void testChatWithToolsAndStream() { +// testEndpointReachability(); +// try { +// OllamaChatRequestBuilder builder = OllamaChatRequestBuilder.getInstance(config.getModel()); +// final Tools.ToolSpecification databaseQueryToolSpecification = Tools.ToolSpecification.builder() +// .functionName("get-employee-details") +// .functionDescription("Get employee details from the database") +// .toolPrompt( +// Tools.PromptFuncDefinition.builder().type("function").function( +// Tools.PromptFuncDefinition.PromptFuncSpec.builder() +// .name("get-employee-details") +// .description("Get employee details from the database") +// .parameters( +// Tools.PromptFuncDefinition.Parameters.builder() +// .type("object") +// .properties( +// new Tools.PropsBuilder() +// .withProperty("employee-name", Tools.PromptFuncDefinition.Property.builder().type("string").description("The name of the employee, e.g. John Doe").required(true).build()) +// .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()) +// .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()) +// .build() +// ) +// .required(List.of("employee-name")) +// .build() +// ).build() +// ).build() +// ) +// .toolFunction(new DBQueryFunction()) +// .build(); +// +// ollamaAPI.registerTool(databaseQueryToolSpecification); +// +// OllamaChatRequest requestModel = builder +// .withMessage(OllamaChatMessageRole.USER, +// "Give me the ID of the employee named 'Rahul Kumar'?") +// .build(); +// +// StringBuffer sb = new StringBuffer(); +// +// OllamaChatResult chatResult = ollamaAPI.chat(requestModel, (s) -> { +// LOG.info(s); +// String substring = s.substring(sb.toString().length()); +// LOG.info(substring); +// sb.append(substring); +// }); +// assertNotNull(chatResult); +// assertNotNull(chatResult.getResponseModel()); +// assertNotNull(chatResult.getResponseModel().getMessage()); +// assertNotNull(chatResult.getResponseModel().getMessage().getContent()); +// assertEquals(sb.toString().trim(), chatResult.getResponseModel().getMessage().getContent().trim()); +// } catch (IOException | OllamaBaseException | InterruptedException e) { +// fail(e); +// } +// } +// +// @Test +// @Order(3) +// void testChatWithStream() { +// testEndpointReachability(); +// try { +// OllamaChatRequestBuilder builder = OllamaChatRequestBuilder.getInstance(config.getModel()); +// OllamaChatRequest requestModel = builder.withMessage(OllamaChatMessageRole.USER, +// "What is the capital of France? And what's France's connection with Mona Lisa?") +// .build(); +// +// StringBuffer sb = new StringBuffer(""); +// +// OllamaChatResult chatResult = ollamaAPI.chat(requestModel, (s) -> { +// LOG.info(s); +// String substring = s.substring(sb.toString().length(), s.length()); +// LOG.info(substring); +// sb.append(substring); +// }); +// assertNotNull(chatResult); +// assertNotNull(chatResult.getResponseModel()); +// assertNotNull(chatResult.getResponseModel().getMessage()); +// assertNotNull(chatResult.getResponseModel().getMessage().getContent()); +// assertEquals(sb.toString().trim(), chatResult.getResponseModel().getMessage().getContent().trim()); +// } catch (IOException | OllamaBaseException | InterruptedException e) { +// fail(e); +// } +// } +// +// @Test +// @Order(3) +// void testChatWithImageFromFileWithHistoryRecognition() { +// testEndpointReachability(); +// try { +// OllamaChatRequestBuilder builder = +// OllamaChatRequestBuilder.getInstance(config.getImageModel()); +// OllamaChatRequest requestModel = +// builder.withMessage(OllamaChatMessageRole.USER, "What's in the picture?",Collections.emptyList(), +// List.of(getImageFileFromClasspath("dog-on-a-boat.jpg"))).build(); +// +// OllamaChatResult chatResult = ollamaAPI.chat(requestModel); +// assertNotNull(chatResult); +// assertNotNull(chatResult.getResponseModel()); +// +// builder.reset(); +// +// requestModel = +// builder.withMessages(chatResult.getChatHistory()) +// .withMessage(OllamaChatMessageRole.USER, "What's the dogs breed?").build(); +// +// chatResult = ollamaAPI.chat(requestModel); +// assertNotNull(chatResult); +// assertNotNull(chatResult.getResponseModel()); +// +// +// } catch (IOException | OllamaBaseException | InterruptedException e) { +// fail(e); +// } +// } +// +// @Test +// @Order(3) +// void testChatWithImageFromURL() { +// testEndpointReachability(); +// try { +// OllamaChatRequestBuilder builder = OllamaChatRequestBuilder.getInstance(config.getImageModel()); +// OllamaChatRequest requestModel = builder.withMessage(OllamaChatMessageRole.USER, "What's in the picture?",Collections.emptyList(), +// "https://t3.ftcdn.net/jpg/02/96/63/80/360_F_296638053_0gUVA4WVBKceGsIr7LNqRWSnkusi07dq.jpg") +// .build(); +// +// OllamaChatResult chatResult = ollamaAPI.chat(requestModel); +// assertNotNull(chatResult); +// } catch (IOException | OllamaBaseException | InterruptedException e) { +// fail(e); +// } +// } +// +// @Test +// @Order(3) +// void testAskModelWithOptionsAndImageFiles() { +// testEndpointReachability(); +// File imageFile = getImageFileFromClasspath("dog-on-a-boat.jpg"); +// try { +// OllamaResult result = +// ollamaAPI.generateWithImageFiles( +// config.getImageModel(), +// "What is in this image?", +// List.of(imageFile), +// new OptionsBuilder().build()); +// assertNotNull(result); +// assertNotNull(result.getResponse()); +// assertFalse(result.getResponse().isEmpty()); +// } catch (IOException | OllamaBaseException | InterruptedException e) { +// fail(e); +// } +// } +// +// @Test +// @Order(3) +// void testAskModelWithOptionsAndImageFilesStreamed() { +// testEndpointReachability(); +// File imageFile = getImageFileFromClasspath("dog-on-a-boat.jpg"); +// try { +// StringBuffer sb = new StringBuffer(""); +// +// OllamaResult result = ollamaAPI.generateWithImageFiles(config.getImageModel(), +// "What is in this image?", List.of(imageFile), new OptionsBuilder().build(), (s) -> { +// LOG.info(s); +// String substring = s.substring(sb.toString().length(), s.length()); +// LOG.info(substring); +// sb.append(substring); +// }); +// assertNotNull(result); +// assertNotNull(result.getResponse()); +// assertFalse(result.getResponse().isEmpty()); +// assertEquals(sb.toString().trim(), result.getResponse().trim()); +// } catch (IOException | OllamaBaseException | InterruptedException e) { +// fail(e); +// } +// } +// +// @Test +// @Order(3) +// void testAskModelWithOptionsAndImageURLs() { +// testEndpointReachability(); +// try { +// OllamaResult result = +// ollamaAPI.generateWithImageURLs( +// config.getImageModel(), +// "What is in this image?", +// List.of( +// "https://t3.ftcdn.net/jpg/02/96/63/80/360_F_296638053_0gUVA4WVBKceGsIr7LNqRWSnkusi07dq.jpg"), +// new OptionsBuilder().build()); +// assertNotNull(result); +// assertNotNull(result.getResponse()); +// assertFalse(result.getResponse().isEmpty()); +// } catch (IOException | OllamaBaseException | InterruptedException | URISyntaxException e) { +// fail(e); +// } +// } +// +// @Test +// @Order(3) +// public void testEmbedding() { +// testEndpointReachability(); +// try { +// OllamaEmbeddingsRequestModel request = OllamaEmbeddingsRequestBuilder +// .getInstance(config.getModel(), "What is the capital of France?").build(); +// +// List embeddings = ollamaAPI.generateEmbeddings(request); +// +// assertNotNull(embeddings); +// assertFalse(embeddings.isEmpty()); +// } catch (IOException | OllamaBaseException | InterruptedException e) { +// fail(e); +// } +// } +//} +// +//class DBQueryFunction implements ToolFunction { +// @Override +// public Object apply(Map arguments) { +// // perform DB operations here +// return String.format("Employee Details {ID: %s, Name: %s, Address: %s, Phone: %s}", UUID.randomUUID(), arguments.get("employee-name"), arguments.get("employee-address"), arguments.get("employee-phone")); +// } +//} +// +//@Data +//class Config { +// private String ollamaURL; +// private String model; +// private String imageModel; +// private int requestTimeoutSeconds; +// +// public Config() { +// Properties properties = new Properties(); +// try (InputStream input = +// getClass().getClassLoader().getResourceAsStream("test-config.properties")) { +// if (input == null) { +// throw new RuntimeException("Sorry, unable to find test-config.properties"); +// } +// properties.load(input); +// this.ollamaURL = properties.getProperty("ollama.url"); +// this.model = properties.getProperty("ollama.model"); +// this.imageModel = properties.getProperty("ollama.model.image"); +// this.requestTimeoutSeconds = +// Integer.parseInt(properties.getProperty("ollama.request-timeout-seconds")); +// } catch (IOException e) { +// throw new RuntimeException("Error loading properties", e); +// } +// } +// +// +//}