diff --git a/.github/workflows/run-tests.yml b/.github/workflows/run-tests.yml index 9ba1114..044436e 100644 --- a/.github/workflows/run-tests.yml +++ b/.github/workflows/run-tests.yml @@ -20,6 +20,10 @@ jobs: with: ref: ${{ github.event.inputs.branch }} + - name: Set up Ollama + run: | + curl -fsSL https://ollama.com/install.sh | sh + - name: Set up JDK 17 uses: actions/setup-java@v3 with: @@ -32,4 +36,7 @@ jobs: run: mvn clean test -Punit-tests - name: Run integration tests - run: mvn clean verify -Pintegration-tests \ No newline at end of file + run: mvn clean verify -Pintegration-tests + env: + USE_EXTERNAL_OLLAMA_HOST: "true" + OLLAMA_HOST: "http://localhost:11434" \ No newline at end of file diff --git a/src/main/java/io/github/ollama4j/utils/Utils.java b/src/main/java/io/github/ollama4j/utils/Utils.java index d854df1..b854b8e 100644 --- a/src/main/java/io/github/ollama4j/utils/Utils.java +++ b/src/main/java/io/github/ollama4j/utils/Utils.java @@ -1,38 +1,45 @@ package io.github.ollama4j.utils; import java.io.ByteArrayOutputStream; +import java.io.File; import java.io.IOException; import java.io.InputStream; import java.net.URI; import java.net.URISyntaxException; import java.net.URL; +import java.util.Objects; import com.fasterxml.jackson.databind.ObjectMapper; import com.fasterxml.jackson.datatype.jsr310.JavaTimeModule; public class Utils { - private static ObjectMapper objectMapper; + private static ObjectMapper objectMapper; - public static ObjectMapper getObjectMapper() { - if(objectMapper == null) { - objectMapper = new ObjectMapper(); - objectMapper.registerModule(new JavaTimeModule()); + public static ObjectMapper getObjectMapper() { + if (objectMapper == null) { + objectMapper = new ObjectMapper(); + objectMapper.registerModule(new JavaTimeModule()); + } + return objectMapper; } - return objectMapper; - } - public static byte[] loadImageBytesFromUrl(String imageUrl) - throws IOException, URISyntaxException { - URL url = new URI(imageUrl).toURL(); - try (InputStream in = url.openStream(); - ByteArrayOutputStream out = new ByteArrayOutputStream()) { - byte[] buffer = new byte[1024]; - int bytesRead; - while ((bytesRead = in.read(buffer)) != -1) { - out.write(buffer, 0, bytesRead); - } - return out.toByteArray(); + public static byte[] loadImageBytesFromUrl(String imageUrl) + throws IOException, URISyntaxException { + URL url = new URI(imageUrl).toURL(); + try (InputStream in = url.openStream(); + ByteArrayOutputStream out = new ByteArrayOutputStream()) { + byte[] buffer = new byte[1024]; + int bytesRead; + while ((bytesRead = in.read(buffer)) != -1) { + out.write(buffer, 0, bytesRead); + } + return out.toByteArray(); + } + } + + public static File getFileFromClasspath(String fileName) { + ClassLoader classLoader = Utils.class.getClassLoader(); + return new File(Objects.requireNonNull(classLoader.getResource(fileName)).getFile()); } - } } diff --git a/src/test/java/io/github/ollama4j/integrationtests/OllamaAPIIntegrationTest.java b/src/test/java/io/github/ollama4j/integrationtests/OllamaAPIIntegrationTest.java index 494c845..1d1e0dc 100644 --- a/src/test/java/io/github/ollama4j/integrationtests/OllamaAPIIntegrationTest.java +++ b/src/test/java/io/github/ollama4j/integrationtests/OllamaAPIIntegrationTest.java @@ -154,7 +154,7 @@ class OllamaAPIIntegrationTest { @Test @Order(6) - void testAskModelWithStructuredOutput() + void testGenerateWithStructuredOutput() throws OllamaBaseException, IOException, InterruptedException, URISyntaxException { api.pullModel(GENERAL_PURPOSE_MODEL); @@ -184,7 +184,7 @@ class OllamaAPIIntegrationTest { @Test @Order(6) - void testAskModelWithDefaultOptions() + void testGennerateModelWithDefaultOptions() throws OllamaBaseException, IOException, InterruptedException, URISyntaxException { api.pullModel(GENERAL_PURPOSE_MODEL); boolean raw = false; @@ -199,7 +199,7 @@ class OllamaAPIIntegrationTest { @Test @Order(7) - void testAskModelWithDefaultOptionsStreamed() + void testGenerateWithDefaultOptionsStreamed() throws OllamaBaseException, IOException, URISyntaxException, InterruptedException { api.pullModel(GENERAL_PURPOSE_MODEL); boolean raw = false; @@ -222,7 +222,7 @@ class OllamaAPIIntegrationTest { @Test @Order(8) - void testAskModelWithOptions() throws OllamaBaseException, IOException, URISyntaxException, + void testGenerateWithOptions() throws OllamaBaseException, IOException, URISyntaxException, InterruptedException, ToolInvocationException { api.pullModel(GENERAL_PURPOSE_MODEL); @@ -305,46 +305,6 @@ class OllamaAPIIntegrationTest { .contains("6"), "Response should contain '6'"); } - @Test - @Order(10) - void testChatWithImageFromURL() throws OllamaBaseException, IOException, InterruptedException, - URISyntaxException, ToolInvocationException { - api.pullModel(VISION_MODEL); - - OllamaChatRequestBuilder builder = OllamaChatRequestBuilder.getInstance(VISION_MODEL); - 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(); - api.registerAnnotatedTools(new OllamaAPIIntegrationTest()); - - OllamaChatResult chatResult = api.chat(requestModel); - assertNotNull(chatResult); - } - - @Test - @Order(10) - void testChatWithImageFromFileWithHistoryRecognition() throws OllamaBaseException, IOException, - URISyntaxException, InterruptedException, ToolInvocationException { - api.pullModel(VISION_MODEL); - OllamaChatRequestBuilder builder = OllamaChatRequestBuilder.getInstance(VISION_MODEL); - OllamaChatRequest requestModel = builder.withMessage(OllamaChatMessageRole.USER, - "What's in the picture?", Collections.emptyList(), - List.of(getImageFileFromClasspath("emoji-smile.jpeg"))).build(); - - OllamaChatResult chatResult = api.chat(requestModel); - assertNotNull(chatResult); - assertNotNull(chatResult.getResponseModel()); - builder.reset(); - - requestModel = builder.withMessages(chatResult.getChatHistory()) - .withMessage(OllamaChatMessageRole.USER, "What's the color?").build(); - - chatResult = api.chat(requestModel); - assertNotNull(chatResult); - assertNotNull(chatResult.getResponseModel()); - } - @Test @Order(11) void testChatWithExplicitToolDefinition() throws OllamaBaseException, IOException, URISyntaxException, @@ -617,9 +577,49 @@ class OllamaAPIIntegrationTest { + chatResult.getResponseModel().getMessage().getContent()); } + @Test + @Order(10) + void testChatWithImageFromURL() throws OllamaBaseException, IOException, InterruptedException, + URISyntaxException, ToolInvocationException { + api.pullModel(VISION_MODEL); + + OllamaChatRequestBuilder builder = OllamaChatRequestBuilder.getInstance(VISION_MODEL); + 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(); + api.registerAnnotatedTools(new OllamaAPIIntegrationTest()); + + OllamaChatResult chatResult = api.chat(requestModel); + assertNotNull(chatResult); + } + + @Test + @Order(10) + void testChatWithImageFromFileWithHistoryRecognition() throws OllamaBaseException, IOException, + URISyntaxException, InterruptedException, ToolInvocationException { + api.pullModel(VISION_MODEL); + OllamaChatRequestBuilder builder = OllamaChatRequestBuilder.getInstance(VISION_MODEL); + OllamaChatRequest requestModel = builder.withMessage(OllamaChatMessageRole.USER, + "What's in the picture?", Collections.emptyList(), + List.of(getImageFileFromClasspath("emoji-smile.jpeg"))).build(); + + OllamaChatResult chatResult = api.chat(requestModel); + assertNotNull(chatResult); + assertNotNull(chatResult.getResponseModel()); + builder.reset(); + + requestModel = builder.withMessages(chatResult.getChatHistory()) + .withMessage(OllamaChatMessageRole.USER, "What's the color?").build(); + + chatResult = api.chat(requestModel); + assertNotNull(chatResult); + assertNotNull(chatResult.getResponseModel()); + } + @Test @Order(17) - void testAskModelWithOptionsAndImageURLs() + void testGenerateWithOptionsAndImageURLs() throws OllamaBaseException, IOException, URISyntaxException, InterruptedException { api.pullModel(VISION_MODEL); @@ -633,7 +633,7 @@ class OllamaAPIIntegrationTest { @Test @Order(18) - void testAskModelWithOptionsAndImageFiles() + void testGenerateWithOptionsAndImageFiles() throws OllamaBaseException, IOException, URISyntaxException, InterruptedException { api.pullModel(VISION_MODEL); File imageFile = getImageFileFromClasspath("roses.jpg"); @@ -650,7 +650,7 @@ class OllamaAPIIntegrationTest { @Test @Order(20) - void testAskModelWithOptionsAndImageFilesStreamed() + void testGenerateWithOptionsAndImageFilesStreamed() throws OllamaBaseException, IOException, URISyntaxException, InterruptedException { api.pullModel(VISION_MODEL);