From 35bf3de62a458cc4837aacec3bdc265386de698c Mon Sep 17 00:00:00 2001 From: amithkoujalgi Date: Sun, 28 Sep 2025 23:30:02 +0530 Subject: [PATCH 1/4] Refactor OllamaAPI to Ollama class and update documentation - Replaced instances of `OllamaAPI` with `Ollama` across the codebase for consistency. - Updated example code snippets in documentation to reflect the new class name. - Enhanced metrics collection setup in the documentation. - Added integration tests for the new `Ollama` class to ensure functionality remains intact. --- docs/METRICS.md | 21 +- docs/blog/2025-03-08-blog/index.md | 375 +++++++++--------- docs/docs/apis-extras/basic-auth.md | 6 +- docs/docs/apis-extras/bearer-auth.md | 6 +- docs/docs/apis-extras/options-builder.md | 6 +- docs/docs/apis-extras/ping.md | 5 +- docs/docs/apis-extras/prompt-builder.md | 7 +- docs/docs/apis-extras/ps.md | 6 +- docs/docs/apis-extras/timeouts.md | 11 +- docs/docs/apis-generate/custom-roles.md | 16 +- docs/docs/intro.md | 10 +- .../ollama4j/{OllamaAPI.java => Ollama.java} | 8 +- .../tools/annotations/OllamaToolService.java | 4 +- .../ollama4j/tools/annotations/ToolSpec.java | 4 +- ...onTest.java => OllamaIntegrationTest.java} | 20 +- .../ollama4j/integrationtests/WithAuth.java | 6 +- .../ollama4j/unittests/TestMockedAPIs.java | 132 +++--- 17 files changed, 326 insertions(+), 317 deletions(-) rename src/main/java/io/github/ollama4j/{OllamaAPI.java => Ollama.java} (99%) rename src/test/java/io/github/ollama4j/integrationtests/{OllamaAPIIntegrationTest.java => OllamaIntegrationTest.java} (99%) diff --git a/docs/METRICS.md b/docs/METRICS.md index 9261a99..83dade6 100644 --- a/docs/METRICS.md +++ b/docs/METRICS.md @@ -17,11 +17,14 @@ The metrics integration provides the following metrics: ### 1. Enable Metrics Collection ```java +import io.github.ollama4j.Ollama; import io.github.ollama4j.OllamaAPI; // Create API instance with metrics enabled -OllamaAPI ollamaAPI = new OllamaAPI(); -ollamaAPI.setMetricsEnabled(true); +Ollama ollama = new Ollama(); +ollamaAPI. + +setMetricsEnabled(true); ``` ### 2. Start Metrics Server @@ -38,11 +41,11 @@ System.out.println("Metrics available at: http://localhost:8080/metrics"); ```java // All API calls are automatically instrumented -boolean isReachable = ollamaAPI.ping(); +boolean isReachable = ollama.ping(); Map format = new HashMap<>(); format.put("type", "json"); -OllamaResult result = ollamaAPI.generateWithFormat( +OllamaResult result = ollama.generateWithFormat( "llama2", "Generate a JSON object", format @@ -100,13 +103,13 @@ ollama_tokens_generated_total{model_name="llama2"} 150.0 ### Enable/Disable Metrics ```java -OllamaAPI ollamaAPI = new OllamaAPI(); +OllamaAPI ollama = new OllamaAPI(); // Enable metrics collection -ollamaAPI.setMetricsEnabled(true); +ollama.setMetricsEnabled(true); // Disable metrics collection (default) -ollamaAPI.setMetricsEnabled(false); +ollama.setMetricsEnabled(false); ``` ### Custom Metrics Server @@ -149,14 +152,14 @@ You can create Grafana dashboards using the metrics. Some useful queries: - Metrics collection adds minimal overhead (~1-2% in most cases) - Metrics are collected asynchronously and don't block API calls -- You can disable metrics in production if needed: `ollamaAPI.setMetricsEnabled(false)` +- You can disable metrics in production if needed: `ollama.setMetricsEnabled(false)` - The metrics server uses minimal resources ## Troubleshooting ### Metrics Not Appearing -1. Ensure metrics are enabled: `ollamaAPI.setMetricsEnabled(true)` +1. Ensure metrics are enabled: `ollama.setMetricsEnabled(true)` 2. Check that the metrics server is running: `http://localhost:8080/metrics` 3. Verify API calls are being made (metrics only appear after API usage) diff --git a/docs/blog/2025-03-08-blog/index.md b/docs/blog/2025-03-08-blog/index.md index 347ed86..637b96b 100644 --- a/docs/blog/2025-03-08-blog/index.md +++ b/docs/blog/2025-03-08-blog/index.md @@ -336,6 +336,7 @@ import com.couchbase.client.java.ClusterOptions; import com.couchbase.client.java.Scope; import com.couchbase.client.java.json.JsonObject; import com.couchbase.client.java.query.QueryResult; +import io.github.ollama4j.Ollama; import io.github.ollama4j.OllamaAPI; import io.github.ollama4j.exceptions.OllamaException; import io.github.ollama4j.exceptions.ToolInvocationException; @@ -356,210 +357,210 @@ import java.util.Map; public class CouchbaseToolCallingExample { - public static void main(String[] args) throws IOException, ToolInvocationException, OllamaException, InterruptedException { - String connectionString = Utilities.getFromEnvVar("CB_CLUSTER_URL"); - String username = Utilities.getFromEnvVar("CB_CLUSTER_USERNAME"); - String password = Utilities.getFromEnvVar("CB_CLUSTER_PASSWORD"); - String bucketName = "travel-sample"; + public static void main(String[] args) throws IOException, ToolInvocationException, OllamaException, InterruptedException { + String connectionString = Utilities.getFromEnvVar("CB_CLUSTER_URL"); + String username = Utilities.getFromEnvVar("CB_CLUSTER_USERNAME"); + String password = Utilities.getFromEnvVar("CB_CLUSTER_PASSWORD"); + String bucketName = "travel-sample"; - Cluster cluster = Cluster.connect( - connectionString, - ClusterOptions.clusterOptions(username, password).environment(env -> { - env.applyProfile("wan-development"); - }) - ); + Cluster cluster = Cluster.connect( + connectionString, + ClusterOptions.clusterOptions(username, password).environment(env -> { + env.applyProfile("wan-development"); + }) + ); - String host = Utilities.getFromConfig("host"); - String modelName = Utilities.getFromConfig("tools_model_mistral"); + String host = Utilities.getFromConfig("host"); + String modelName = Utilities.getFromConfig("tools_model_mistral"); - OllamaAPI ollamaAPI = new OllamaAPI(host); - ollamaAPI.setRequestTimeoutSeconds(60); + Ollama ollama = new Ollama(host); + ollama.setRequestTimeoutSeconds(60); - Tools.ToolSpecification callSignFinderToolSpec = getCallSignFinderToolSpec(cluster, bucketName); - Tools.ToolSpecification callSignUpdaterToolSpec = getCallSignUpdaterToolSpec(cluster, bucketName); + Tools.ToolSpecification callSignFinderToolSpec = getCallSignFinderToolSpec(cluster, bucketName); + Tools.ToolSpecification callSignUpdaterToolSpec = getCallSignUpdaterToolSpec(cluster, bucketName); - ollamaAPI.registerTool(callSignFinderToolSpec); - ollamaAPI.registerTool(callSignUpdaterToolSpec); + ollama.registerTool(callSignFinderToolSpec); + ollama.registerTool(callSignUpdaterToolSpec); - String prompt1 = "What is the call-sign of Astraeus?"; - for (OllamaToolsResult.ToolResult r : ollamaAPI.generateWithTools(modelName, new Tools.PromptBuilder() - .withToolSpecification(callSignFinderToolSpec) - .withPrompt(prompt1) - .build(), new OptionsBuilder().build()).getToolResults()) { - AirlineDetail airlineDetail = (AirlineDetail) r.getResult(); - System.out.println(String.format("[Result of tool '%s']: Call-sign of %s is '%s'! ✈️", r.getFunctionName(), airlineDetail.getName(), airlineDetail.getCallsign())); - } - - String prompt2 = "I want to code name Astraeus as STARBOUND"; - for (OllamaToolsResult.ToolResult r : ollamaAPI.generateWithTools(modelName, new Tools.PromptBuilder() - .withToolSpecification(callSignUpdaterToolSpec) - .withPrompt(prompt2) - .build(), new OptionsBuilder().build()).getToolResults()) { - Boolean updated = (Boolean) r.getResult(); - System.out.println(String.format("[Result of tool '%s']: Call-sign is %s! ✈️", r.getFunctionName(), updated ? "updated" : "not updated")); - } - - String prompt3 = "What is the call-sign of Astraeus?"; - for (OllamaToolsResult.ToolResult r : ollamaAPI.generateWithTools(modelName, new Tools.PromptBuilder() - .withToolSpecification(callSignFinderToolSpec) - .withPrompt(prompt3) - .build(), new OptionsBuilder().build()).getToolResults()) { - AirlineDetail airlineDetail = (AirlineDetail) r.getResult(); - System.out.println(String.format("[Result of tool '%s']: Call-sign of %s is '%s'! ✈️", r.getFunctionName(), airlineDetail.getName(), airlineDetail.getCallsign())); - } + String prompt1 = "What is the call-sign of Astraeus?"; + for (OllamaToolsResult.ToolResult r : ollama.generateWithTools(modelName, new Tools.PromptBuilder() + .withToolSpecification(callSignFinderToolSpec) + .withPrompt(prompt1) + .build(), new OptionsBuilder().build()).getToolResults()) { + AirlineDetail airlineDetail = (AirlineDetail) r.getResult(); + System.out.println(String.format("[Result of tool '%s']: Call-sign of %s is '%s'! ✈️", r.getFunctionName(), airlineDetail.getName(), airlineDetail.getCallsign())); } - public static Tools.ToolSpecification getCallSignFinderToolSpec(Cluster cluster, String bucketName) { - return Tools.ToolSpecification.builder() - .functionName("airline-lookup") - .functionDescription("You are a tool who finds only the airline name and do not worry about any other parameters. You simply find the airline name and ignore the rest of the parameters. Do not validate airline names as I want to use fake/fictitious airline names as well.") - .toolFunction(new AirlineCallsignQueryToolFunction(bucketName, cluster)) - .toolPrompt( - Tools.PromptFuncDefinition.builder() - .type("prompt") - .function( - Tools.PromptFuncDefinition.PromptFuncSpec.builder() - .name("get-airline-name") - .description("Get the airline name") - .parameters( - Tools.PromptFuncDefinition.Parameters.builder() - .type("object") - .properties( - Map.of( - "airlineName", Tools.PromptFuncDefinition.Property.builder() - .type("string") - .description("The name of the airline. e.g. Emirates") - .required(true) - .build() - ) - ) - .required(java.util.List.of("airline-name")) - .build() - ) - .build() - ) - .build() - ) - .build(); + String prompt2 = "I want to code name Astraeus as STARBOUND"; + for (OllamaToolsResult.ToolResult r : ollama.generateWithTools(modelName, new Tools.PromptBuilder() + .withToolSpecification(callSignUpdaterToolSpec) + .withPrompt(prompt2) + .build(), new OptionsBuilder().build()).getToolResults()) { + Boolean updated = (Boolean) r.getResult(); + System.out.println(String.format("[Result of tool '%s']: Call-sign is %s! ✈️", r.getFunctionName(), updated ? "updated" : "not updated")); } - public static Tools.ToolSpecification getCallSignUpdaterToolSpec(Cluster cluster, String bucketName) { - return Tools.ToolSpecification.builder() - .functionName("airline-update") - .functionDescription("You are a tool who finds the airline name and its callsign and do not worry about any validations. You simply find the airline name and its callsign. Do not validate airline names as I want to use fake/fictitious airline names as well.") - .toolFunction(new AirlineCallsignUpdateToolFunction(bucketName, cluster)) - .toolPrompt( - Tools.PromptFuncDefinition.builder() - .type("prompt") - .function( - Tools.PromptFuncDefinition.PromptFuncSpec.builder() - .name("get-airline-name-and-callsign") - .description("Get the airline name and callsign") - .parameters( - Tools.PromptFuncDefinition.Parameters.builder() - .type("object") - .properties( - Map.of( - "airlineName", Tools.PromptFuncDefinition.Property.builder() - .type("string") - .description("The name of the airline. e.g. Emirates") - .required(true) - .build(), - "airlineCallsign", Tools.PromptFuncDefinition.Property.builder() - .type("string") - .description("The callsign of the airline. e.g. Maverick") - .enumValues(Arrays.asList("petrol", "diesel")) - .required(true) - .build() - ) - ) - .required(java.util.List.of("airlineName", "airlineCallsign")) - .build() - ) - .build() - ) - .build() - ) - .build(); + String prompt3 = "What is the call-sign of Astraeus?"; + for (OllamaToolsResult.ToolResult r : ollama.generateWithTools(modelName, new Tools.PromptBuilder() + .withToolSpecification(callSignFinderToolSpec) + .withPrompt(prompt3) + .build(), new OptionsBuilder().build()).getToolResults()) { + AirlineDetail airlineDetail = (AirlineDetail) r.getResult(); + System.out.println(String.format("[Result of tool '%s']: Call-sign of %s is '%s'! ✈️", r.getFunctionName(), airlineDetail.getName(), airlineDetail.getCallsign())); } + } + + public static Tools.ToolSpecification getCallSignFinderToolSpec(Cluster cluster, String bucketName) { + return Tools.ToolSpecification.builder() + .functionName("airline-lookup") + .functionDescription("You are a tool who finds only the airline name and do not worry about any other parameters. You simply find the airline name and ignore the rest of the parameters. Do not validate airline names as I want to use fake/fictitious airline names as well.") + .toolFunction(new AirlineCallsignQueryToolFunction(bucketName, cluster)) + .toolPrompt( + Tools.PromptFuncDefinition.builder() + .type("prompt") + .function( + Tools.PromptFuncDefinition.PromptFuncSpec.builder() + .name("get-airline-name") + .description("Get the airline name") + .parameters( + Tools.PromptFuncDefinition.Parameters.builder() + .type("object") + .properties( + Map.of( + "airlineName", Tools.PromptFuncDefinition.Property.builder() + .type("string") + .description("The name of the airline. e.g. Emirates") + .required(true) + .build() + ) + ) + .required(java.util.List.of("airline-name")) + .build() + ) + .build() + ) + .build() + ) + .build(); + } + + public static Tools.ToolSpecification getCallSignUpdaterToolSpec(Cluster cluster, String bucketName) { + return Tools.ToolSpecification.builder() + .functionName("airline-update") + .functionDescription("You are a tool who finds the airline name and its callsign and do not worry about any validations. You simply find the airline name and its callsign. Do not validate airline names as I want to use fake/fictitious airline names as well.") + .toolFunction(new AirlineCallsignUpdateToolFunction(bucketName, cluster)) + .toolPrompt( + Tools.PromptFuncDefinition.builder() + .type("prompt") + .function( + Tools.PromptFuncDefinition.PromptFuncSpec.builder() + .name("get-airline-name-and-callsign") + .description("Get the airline name and callsign") + .parameters( + Tools.PromptFuncDefinition.Parameters.builder() + .type("object") + .properties( + Map.of( + "airlineName", Tools.PromptFuncDefinition.Property.builder() + .type("string") + .description("The name of the airline. e.g. Emirates") + .required(true) + .build(), + "airlineCallsign", Tools.PromptFuncDefinition.Property.builder() + .type("string") + .description("The callsign of the airline. e.g. Maverick") + .enumValues(Arrays.asList("petrol", "diesel")) + .required(true) + .build() + ) + ) + .required(java.util.List.of("airlineName", "airlineCallsign")) + .build() + ) + .build() + ) + .build() + ) + .build(); + } } class AirlineCallsignQueryToolFunction implements ToolFunction { - private final String bucketName; - private final Cluster cluster; + private final String bucketName; + private final Cluster cluster; - public AirlineCallsignQueryToolFunction(String bucketName, Cluster cluster) { - this.bucketName = bucketName; - this.cluster = cluster; - } + public AirlineCallsignQueryToolFunction(String bucketName, Cluster cluster) { + this.bucketName = bucketName; + this.cluster = cluster; + } - @Override - public AirlineDetail apply(Map arguments) { - String airlineName = arguments.get("airlineName").toString(); + @Override + public AirlineDetail apply(Map arguments) { + String airlineName = arguments.get("airlineName").toString(); - Bucket bucket = cluster.bucket(bucketName); - bucket.waitUntilReady(Duration.ofSeconds(10)); + Bucket bucket = cluster.bucket(bucketName); + bucket.waitUntilReady(Duration.ofSeconds(10)); - Scope inventoryScope = bucket.scope("inventory"); - QueryResult result = inventoryScope.query(String.format("SELECT * FROM airline WHERE name = '%s';", airlineName)); + Scope inventoryScope = bucket.scope("inventory"); + QueryResult result = inventoryScope.query(String.format("SELECT * FROM airline WHERE name = '%s';", airlineName)); - JsonObject row = (JsonObject) result.rowsAsObject().get(0).get("airline"); - return new AirlineDetail(row.getString("callsign"), row.getString("name"), row.getString("country")); - } + JsonObject row = (JsonObject) result.rowsAsObject().get(0).get("airline"); + return new AirlineDetail(row.getString("callsign"), row.getString("name"), row.getString("country")); + } } class AirlineCallsignUpdateToolFunction implements ToolFunction { - private final String bucketName; - private final Cluster cluster; + private final String bucketName; + private final Cluster cluster; - public AirlineCallsignUpdateToolFunction(String bucketName, Cluster cluster) { - this.bucketName = bucketName; - this.cluster = cluster; + public AirlineCallsignUpdateToolFunction(String bucketName, Cluster cluster) { + this.bucketName = bucketName; + this.cluster = cluster; + } + + + @Override + public Boolean apply(Map arguments) { + String airlineName = arguments.get("airlineName").toString(); + String airlineNewCallsign = arguments.get("airlineCallsign").toString(); + + Bucket bucket = cluster.bucket(bucketName); + bucket.waitUntilReady(Duration.ofSeconds(10)); + + Scope inventoryScope = bucket.scope("inventory"); + String query = String.format("SELECT * FROM airline WHERE name = '%s';", airlineName); + + QueryResult result; + try { + result = inventoryScope.query(query); + } catch (Exception e) { + throw new RuntimeException("Error executing query", e); } - - @Override - public Boolean apply(Map arguments) { - String airlineName = arguments.get("airlineName").toString(); - String airlineNewCallsign = arguments.get("airlineCallsign").toString(); - - Bucket bucket = cluster.bucket(bucketName); - bucket.waitUntilReady(Duration.ofSeconds(10)); - - Scope inventoryScope = bucket.scope("inventory"); - String query = String.format("SELECT * FROM airline WHERE name = '%s';", airlineName); - - QueryResult result; - try { - result = inventoryScope.query(query); - } catch (Exception e) { - throw new RuntimeException("Error executing query", e); - } - - if (result.rowsAsObject().isEmpty()) { - throw new RuntimeException("Airline not found with name: " + airlineName); - } - - JsonObject row = (JsonObject) result.rowsAsObject().get(0).get("airline"); - - if (row == null) { - throw new RuntimeException("Airline data is missing or corrupted."); - } - - String currentCallsign = row.getString("callsign"); - - if (!airlineNewCallsign.equals(currentCallsign)) { - JsonObject updateQuery = JsonObject.create() - .put("callsign", airlineNewCallsign); - - inventoryScope.query(String.format( - "UPDATE airline SET callsign = '%s' WHERE name = '%s';", - airlineNewCallsign, airlineName - )); - return true; - } - return false; + if (result.rowsAsObject().isEmpty()) { + throw new RuntimeException("Airline not found with name: " + airlineName); } + + JsonObject row = (JsonObject) result.rowsAsObject().get(0).get("airline"); + + if (row == null) { + throw new RuntimeException("Airline data is missing or corrupted."); + } + + String currentCallsign = row.getString("callsign"); + + if (!airlineNewCallsign.equals(currentCallsign)) { + JsonObject updateQuery = JsonObject.create() + .put("callsign", airlineNewCallsign); + + inventoryScope.query(String.format( + "UPDATE airline SET callsign = '%s' WHERE name = '%s';", + airlineNewCallsign, airlineName + )); + return true; + } + return false; + } } @SuppressWarnings("ALL") @@ -567,9 +568,9 @@ class AirlineCallsignUpdateToolFunction implements ToolFunction { @AllArgsConstructor @NoArgsConstructor class AirlineDetail { - private String callsign; - private String name; - private String country; + private String callsign; + private String name; + private String country; } ``` @@ -578,9 +579,9 @@ class AirlineDetail { #### 1. Ollama API Client Setup ```javascript -OllamaAPI ollamaAPI = new OllamaAPI(host); +OllamaAPI ollama = new OllamaAPI(host); -ollamaAPI.setRequestTimeoutSeconds(60); +ollama.setRequestTimeoutSeconds(60); ``` Here, we initialize the Ollama API client and configure it with the host of the Ollama server, where the model is hosted @@ -595,7 +596,7 @@ queries the database for airline details based on the airline name. ```javascript Tools.ToolSpecification callSignFinderToolSpec = getCallSignFinderToolSpec(cluster, bucketName); -ollamaAPI.registerTool(callSignFinderToolSpec); +ollama.registerTool(callSignFinderToolSpec); ``` This step registers custom tools with Ollama that allows the tool-calling model to invoke database queries. @@ -619,7 +620,7 @@ String prompt = "What is the call-sign of Astraeus?"; #### 5. Generating Results with Tools ```javascript -for (OllamaToolsResult.ToolResult r : ollamaAPI.generateWithTools(modelName, new Tools.PromptBuilder() +for (OllamaToolsResult.ToolResult r : ollama.generateWithTools(modelName, new Tools.PromptBuilder() .withToolSpecification(callSignFinderToolSpec) .withPrompt(prompt) .build(), new OptionsBuilder().build()).getToolResults()) { @@ -649,7 +650,7 @@ then update the airline’s callsign. ```javascript Tools.ToolSpecification callSignUpdaterToolSpec = getCallSignUpdaterToolSpec(cluster, bucketName); -ollamaAPI.registerTool(callSignUpdaterToolSpec); +ollama.registerTool(callSignUpdaterToolSpec); ``` The tool will execute a Couchbase N1QL query to update the airline’s callsign. @@ -671,7 +672,7 @@ And then we invoke the model with the new prompt. ```javascript String prompt = "I want to code name Astraeus as STARBOUND"; -for (OllamaToolsResult.ToolResult r : ollamaAPI.generateWithTools(modelName, new Tools.PromptBuilder() +for (OllamaToolsResult.ToolResult r : ollama.generateWithTools(modelName, new Tools.PromptBuilder() .withToolSpecification(callSignUpdaterToolSpec) .withPrompt(prompt) .build(), new OptionsBuilder().build()).getToolResults()) { diff --git a/docs/docs/apis-extras/basic-auth.md b/docs/docs/apis-extras/basic-auth.md index 1e96177..5d2a0a6 100644 --- a/docs/docs/apis-extras/basic-auth.md +++ b/docs/docs/apis-extras/basic-auth.md @@ -10,7 +10,7 @@ Ollama server would be setup behind a gateway/reverse proxy with basic auth. After configuring basic authentication, all subsequent requests will include the Basic Auth header. ```java -import io.github.ollama4j.OllamaAPI; +import io.github.ollama4j.Ollama; public class Main { @@ -18,9 +18,9 @@ public class Main { String host = "http://localhost:11434/"; - OllamaAPI ollamaAPI = new OllamaAPI(host); + Ollama ollama = new Ollama(host); - ollamaAPI.setBasicAuth("username", "password"); + ollama.setBasicAuth("username", "password"); } } ``` \ No newline at end of file diff --git a/docs/docs/apis-extras/bearer-auth.md b/docs/docs/apis-extras/bearer-auth.md index cdd4b3a..5f24e52 100644 --- a/docs/docs/apis-extras/bearer-auth.md +++ b/docs/docs/apis-extras/bearer-auth.md @@ -10,7 +10,7 @@ Ollama server would be setup behind a gateway/reverse proxy with bearer auth. After configuring bearer authentication, all subsequent requests will include the Bearer Auth header. ```java -import io.github.ollama4j.OllamaAPI; +import io.github.ollama4j.Ollama; public class Main { @@ -18,9 +18,9 @@ public class Main { String host = "http://localhost:11434/"; - OllamaAPI ollamaAPI = new OllamaAPI(host); + Ollama ollama = new Ollama(host); - ollamaAPI.setBearerAuth("YOUR-TOKEN"); + ollama.setBearerAuth("YOUR-TOKEN"); } } ``` \ No newline at end of file diff --git a/docs/docs/apis-extras/options-builder.md b/docs/docs/apis-extras/options-builder.md index 10aeea5..a838950 100644 --- a/docs/docs/apis-extras/options-builder.md +++ b/docs/docs/apis-extras/options-builder.md @@ -36,7 +36,7 @@ from [javadoc](https://ollama4j.github.io/ollama4j/apidocs/io/github/ollama4j/ol ## Build an empty `Options` object ```java -import io.github.ollama4j.OllamaAPI; +import io.github.ollama4j.Ollama; import io.github.ollama4j.utils.Options; import io.github.ollama4j.utils.OptionsBuilder; @@ -46,7 +46,7 @@ public class Main { String host = "http://localhost:11434/"; - OllamaAPI ollamaAPI = new OllamaAPI(host); + Ollama ollama = new Ollama(host); Options options = new OptionsBuilder().build(); } @@ -65,7 +65,7 @@ public class Main { String host = "http://localhost:11434/"; - OllamaAPI ollamaAPI = new OllamaAPI(host); + OllamaAPI ollama = new OllamaAPI(host); Options options = new OptionsBuilder() diff --git a/docs/docs/apis-extras/ping.md b/docs/docs/apis-extras/ping.md index 256c26b..34153b1 100644 --- a/docs/docs/apis-extras/ping.md +++ b/docs/docs/apis-extras/ping.md @@ -7,6 +7,7 @@ sidebar_position: 5 This API lets you check the reachability of Ollama server. ```java +import io.github.ollama4j.Ollama; import io.github.ollama4j.OllamaAPI; public class Main { @@ -14,9 +15,9 @@ public class Main { public static void main(String[] args) { String host = "http://localhost:11434/"; - OllamaAPI ollamaAPI = new OllamaAPI(host); + Ollama ollama = new Ollama(host); - ollamaAPI.ping(); + ollama.ping(); } } ``` \ No newline at end of file diff --git a/docs/docs/apis-extras/prompt-builder.md b/docs/docs/apis-extras/prompt-builder.md index 3240591..9101e54 100644 --- a/docs/docs/apis-extras/prompt-builder.md +++ b/docs/docs/apis-extras/prompt-builder.md @@ -8,6 +8,7 @@ This is designed for prompt engineering. It allows you to easily build the promp inferences. ```java +import io.github.ollama4j.Ollama; import io.github.ollama4j.OllamaAPI; import io.github.ollama4j.models.response.OllamaResult; import io.github.ollama4j.types.OllamaModelType; @@ -18,8 +19,8 @@ public class Main { public static void main(String[] args) throws Exception { String host = "http://localhost:11434/"; - OllamaAPI ollamaAPI = new OllamaAPI(host); - ollamaAPI.setRequestTimeoutSeconds(10); + Ollama ollama = new Ollama(host); + ollama.setRequestTimeoutSeconds(10); String model = OllamaModelType.PHI; @@ -43,7 +44,7 @@ public class Main { .add("How do I read a file in Go and print its contents to stdout?"); boolean raw = false; - OllamaResult response = ollamaAPI.generate(model, promptBuilder.build(), raw, new OptionsBuilder().build()); + OllamaResult response = ollama.generate(model, promptBuilder.build(), raw, new OptionsBuilder().build()); System.out.println(response.getResponse()); } } diff --git a/docs/docs/apis-extras/ps.md b/docs/docs/apis-extras/ps.md index 43b0af5..8e4b3ea 100644 --- a/docs/docs/apis-extras/ps.md +++ b/docs/docs/apis-extras/ps.md @@ -11,15 +11,15 @@ This API corresponds to the [PS](https://github.com/ollama/ollama/blob/main/docs ```java package io.github.ollama4j.localtests; -import io.github.ollama4j.OllamaAPI; +import io.github.ollama4j.Ollama; import io.github.ollama4j.models.ps.ModelProcessesResult; public class Main { public static void main(String[] args) { - OllamaAPI ollamaAPI = new OllamaAPI("http://localhost:11434"); + Ollama ollama = new Ollama("http://localhost:11434"); - ModelProcessesResult response = ollamaAPI.ps(); + ModelProcessesResult response = ollama.ps(); System.out.println(response); } diff --git a/docs/docs/apis-extras/timeouts.md b/docs/docs/apis-extras/timeouts.md index 2b0b52c..eb3354d 100644 --- a/docs/docs/apis-extras/timeouts.md +++ b/docs/docs/apis-extras/timeouts.md @@ -9,17 +9,18 @@ sidebar_position: 2 This API lets you set the request timeout for the Ollama client. ```java +import io.github.ollama4j.Ollama; import io.github.ollama4j.OllamaAPI; public class Main { - public static void main(String[] args) { + public static void main(String[] args) { - String host = "http://localhost:11434/"; + String host = "http://localhost:11434/"; - OllamaAPI ollamaAPI = new OllamaAPI(host); + Ollama ollama = new Ollama(host); - ollamaAPI.setRequestTimeoutSeconds(10); - } + ollama.setRequestTimeoutSeconds(10); + } } ``` \ No newline at end of file diff --git a/docs/docs/apis-generate/custom-roles.md b/docs/docs/apis-generate/custom-roles.md index 44df8b1..9858792 100644 --- a/docs/docs/apis-generate/custom-roles.md +++ b/docs/docs/apis-generate/custom-roles.md @@ -16,6 +16,7 @@ _Base roles are `SYSTEM`, `USER`, `ASSISTANT`, `TOOL`._ #### Add new role ```java +import io.github.ollama4j.Ollama; import io.github.ollama4j.OllamaAPI; import io.github.ollama4j.models.chat.OllamaChatMessageRole; @@ -23,9 +24,9 @@ public class Main { public static void main(String[] args) { String host = "http://localhost:11434/"; - OllamaAPI ollamaAPI = new OllamaAPI(host); + Ollama ollama = new Ollama(host); - OllamaChatMessageRole customRole = ollamaAPI.addCustomRole("custom-role"); + OllamaChatMessageRole customRole = ollama.addCustomRole("custom-role"); } } ``` @@ -33,16 +34,16 @@ public class Main { #### List roles ```java -import io.github.ollama4j.OllamaAPI; +import io.github.ollama4j.Ollama; import io.github.ollama4j.models.chat.OllamaChatMessageRole; public class Main { public static void main(String[] args) { String host = "http://localhost:11434/"; - OllamaAPI ollamaAPI = new OllamaAPI(host); + Ollama ollama = new Ollama(host); - List roles = ollamaAPI.listRoles(); + List roles = ollama.listRoles(); } } ``` @@ -50,6 +51,7 @@ public class Main { #### Get role ```java +import io.github.ollama4j.Ollama; import io.github.ollama4j.OllamaAPI; import io.github.ollama4j.models.chat.OllamaChatMessageRole; @@ -57,9 +59,9 @@ public class Main { public static void main(String[] args) { String host = "http://localhost:11434/"; - OllamaAPI ollamaAPI = new OllamaAPI(host); + Ollama ollama = new Ollama(host); - List roles = ollamaAPI.getRole("custom-role"); + List roles = ollama.getRole("custom-role"); } } ``` \ No newline at end of file diff --git a/docs/docs/intro.md b/docs/docs/intro.md index 23ddb99..f237a31 100644 --- a/docs/docs/intro.md +++ b/docs/docs/intro.md @@ -112,14 +112,15 @@ or use other suitable implementations. Create a new Java class in your project and add this code. ```java +import io.github.ollama4j.Ollama; import io.github.ollama4j.OllamaAPI; public class OllamaAPITest { public static void main(String[] args) { - OllamaAPI ollamaAPI = new OllamaAPI(); + Ollama ollama = new Ollama(); - boolean isOllamaServerReachable = ollamaAPI.ping(); + boolean isOllamaServerReachable = ollama.ping(); System.out.println("Is Ollama server running: " + isOllamaServerReachable); } @@ -130,6 +131,7 @@ This uses the default Ollama host as `http://localhost:11434`. Specify a different Ollama host that you want to connect to. ```java +import io.github.ollama4j.Ollama; import io.github.ollama4j.OllamaAPI; public class OllamaAPITest { @@ -137,9 +139,9 @@ public class OllamaAPITest { public static void main(String[] args) { String host = "http://localhost:11434/"; - OllamaAPI ollamaAPI = new OllamaAPI(host); + Ollama ollama = new Ollama(host); - boolean isOllamaServerReachable = ollamaAPI.ping(); + boolean isOllamaServerReachable = ollama.ping(); System.out.println("Is Ollama server running: " + isOllamaServerReachable); } diff --git a/src/main/java/io/github/ollama4j/OllamaAPI.java b/src/main/java/io/github/ollama4j/Ollama.java similarity index 99% rename from src/main/java/io/github/ollama4j/OllamaAPI.java rename to src/main/java/io/github/ollama4j/Ollama.java index 7e095d2..5357a70 100644 --- a/src/main/java/io/github/ollama4j/OllamaAPI.java +++ b/src/main/java/io/github/ollama4j/Ollama.java @@ -53,9 +53,9 @@ import org.slf4j.LoggerFactory; *

This class provides methods for model management, chat, embeddings, tool registration, and more. */ @SuppressWarnings({"DuplicatedCode", "resource", "SpellCheckingInspection"}) -public class OllamaAPI { +public class Ollama { - private static final Logger LOG = LoggerFactory.getLogger(OllamaAPI.class); + private static final Logger LOG = LoggerFactory.getLogger(Ollama.class); private final String host; private Auth auth; @@ -107,7 +107,7 @@ public class OllamaAPI { /** * Instantiates the Ollama API with the default Ollama host: {@code http://localhost:11434} */ - public OllamaAPI() { + public Ollama() { this.host = "http://localhost:11434"; } @@ -116,7 +116,7 @@ public class OllamaAPI { * * @param host the host address of the Ollama server */ - public OllamaAPI(String host) { + public Ollama(String host) { if (host.endsWith("/")) { this.host = host.substring(0, host.length() - 1); } else { diff --git a/src/main/java/io/github/ollama4j/tools/annotations/OllamaToolService.java b/src/main/java/io/github/ollama4j/tools/annotations/OllamaToolService.java index d044fa5..a3b452a 100644 --- a/src/main/java/io/github/ollama4j/tools/annotations/OllamaToolService.java +++ b/src/main/java/io/github/ollama4j/tools/annotations/OllamaToolService.java @@ -8,7 +8,7 @@ */ package io.github.ollama4j.tools.annotations; -import io.github.ollama4j.OllamaAPI; +import io.github.ollama4j.Ollama; import java.lang.annotation.ElementType; import java.lang.annotation.Retention; import java.lang.annotation.RetentionPolicy; @@ -18,7 +18,7 @@ import java.lang.annotation.Target; * Annotation to mark a class as an Ollama tool service. *

* When a class is annotated with {@code @OllamaToolService}, the method - * {@link OllamaAPI#registerAnnotatedTools()} can be used to automatically register all tool provider + * {@link Ollama#registerAnnotatedTools()} can be used to automatically register all tool provider * classes specified in the {@link #providers()} array. All methods in those provider classes that are * annotated with {@link ToolSpec} will be registered as tools. *

diff --git a/src/main/java/io/github/ollama4j/tools/annotations/ToolSpec.java b/src/main/java/io/github/ollama4j/tools/annotations/ToolSpec.java index 04a3efb..a5206ca 100644 --- a/src/main/java/io/github/ollama4j/tools/annotations/ToolSpec.java +++ b/src/main/java/io/github/ollama4j/tools/annotations/ToolSpec.java @@ -8,7 +8,7 @@ */ package io.github.ollama4j.tools.annotations; -import io.github.ollama4j.OllamaAPI; +import io.github.ollama4j.Ollama; import java.lang.annotation.ElementType; import java.lang.annotation.Retention; import java.lang.annotation.RetentionPolicy; @@ -16,7 +16,7 @@ import java.lang.annotation.Target; /** * Annotation to mark a method as a tool that can be registered automatically by - * {@link OllamaAPI#registerAnnotatedTools()}. + * {@link Ollama#registerAnnotatedTools()}. *

* Methods annotated with {@code @ToolSpec} will be discovered and registered as tools * when the containing class is specified as a provider in {@link OllamaToolService}. diff --git a/src/test/java/io/github/ollama4j/integrationtests/OllamaAPIIntegrationTest.java b/src/test/java/io/github/ollama4j/integrationtests/OllamaIntegrationTest.java similarity index 99% rename from src/test/java/io/github/ollama4j/integrationtests/OllamaAPIIntegrationTest.java rename to src/test/java/io/github/ollama4j/integrationtests/OllamaIntegrationTest.java index c86856e..53e0ef5 100644 --- a/src/test/java/io/github/ollama4j/integrationtests/OllamaAPIIntegrationTest.java +++ b/src/test/java/io/github/ollama4j/integrationtests/OllamaIntegrationTest.java @@ -10,7 +10,7 @@ package io.github.ollama4j.integrationtests; import static org.junit.jupiter.api.Assertions.*; -import io.github.ollama4j.OllamaAPI; +import io.github.ollama4j.Ollama; import io.github.ollama4j.exceptions.OllamaException; import io.github.ollama4j.impl.ConsoleOutputChatTokenHandler; import io.github.ollama4j.impl.ConsoleOutputGenerateTokenHandler; @@ -44,11 +44,11 @@ import org.testcontainers.ollama.OllamaContainer; @OllamaToolService(providers = {AnnotatedTool.class}) @TestMethodOrder(OrderAnnotation.class) @SuppressWarnings({"HttpUrlsUsage", "SpellCheckingInspection", "FieldCanBeLocal", "ConstantValue"}) -class OllamaAPIIntegrationTest { - private static final Logger LOG = LoggerFactory.getLogger(OllamaAPIIntegrationTest.class); +class OllamaIntegrationTest { + private static final Logger LOG = LoggerFactory.getLogger(OllamaIntegrationTest.class); private static OllamaContainer ollama; - private static OllamaAPI api; + private static Ollama api; private static final String EMBEDDING_MODEL = "all-minilm"; private static final String VISION_MODEL = "moondream:1.8b"; @@ -81,7 +81,7 @@ class OllamaAPIIntegrationTest { Properties props = new Properties(); try { props.load( - OllamaAPIIntegrationTest.class + OllamaIntegrationTest.class .getClassLoader() .getResourceAsStream("test-config.properties")); } catch (Exception e) { @@ -103,7 +103,7 @@ class OllamaAPIIntegrationTest { if (useExternalOllamaHost) { LOG.info("Using external Ollama host: {}", ollamaHost); - api = new OllamaAPI(ollamaHost); + api = new Ollama(ollamaHost); } else { throw new RuntimeException( "USE_EXTERNAL_OLLAMA_HOST is not set so, we will be using Testcontainers" @@ -124,7 +124,7 @@ class OllamaAPIIntegrationTest { ollama.start(); LOG.info("Using Testcontainer Ollama host..."); api = - new OllamaAPI( + new Ollama( "http://" + ollama.getHost() + ":" @@ -143,8 +143,8 @@ class OllamaAPIIntegrationTest { @Test @Order(1) void shouldThrowConnectExceptionForWrongEndpoint() { - OllamaAPI ollamaAPI = new OllamaAPI("http://wrong-host:11434"); - assertThrows(OllamaException.class, ollamaAPI::listModels); + Ollama ollama = new Ollama("http://wrong-host:11434"); + assertThrows(OllamaException.class, ollama::listModels); } /** @@ -778,7 +778,7 @@ class OllamaAPIIntegrationTest { Collections.emptyList(), "https://t3.ftcdn.net/jpg/02/96/63/80/360_F_296638053_0gUVA4WVBKceGsIr7LNqRWSnkusi07dq.jpg") .build(); - api.registerAnnotatedTools(new OllamaAPIIntegrationTest()); + api.registerAnnotatedTools(new OllamaIntegrationTest()); OllamaChatResult chatResult = api.chat(requestModel, null); assertNotNull(chatResult); diff --git a/src/test/java/io/github/ollama4j/integrationtests/WithAuth.java b/src/test/java/io/github/ollama4j/integrationtests/WithAuth.java index e4a5fee..fe22ea3 100644 --- a/src/test/java/io/github/ollama4j/integrationtests/WithAuth.java +++ b/src/test/java/io/github/ollama4j/integrationtests/WithAuth.java @@ -10,7 +10,7 @@ package io.github.ollama4j.integrationtests; import static org.junit.jupiter.api.Assertions.*; -import io.github.ollama4j.OllamaAPI; +import io.github.ollama4j.Ollama; import io.github.ollama4j.exceptions.OllamaException; import io.github.ollama4j.models.generate.OllamaGenerateRequest; import io.github.ollama4j.models.generate.OllamaGenerateRequestBuilder; @@ -62,7 +62,7 @@ public class WithAuth { private static OllamaContainer ollama; private static GenericContainer nginx; - private static OllamaAPI api; + private static Ollama api; @BeforeAll static void setUp() { @@ -74,7 +74,7 @@ public class WithAuth { LOG.info("Using Testcontainer Ollama host..."); - api = new OllamaAPI("http://" + nginx.getHost() + ":" + nginx.getMappedPort(NGINX_PORT)); + api = new Ollama("http://" + nginx.getHost() + ":" + nginx.getMappedPort(NGINX_PORT)); api.setRequestTimeoutSeconds(120); api.setNumberOfRetriesForModelPull(3); diff --git a/src/test/java/io/github/ollama4j/unittests/TestMockedAPIs.java b/src/test/java/io/github/ollama4j/unittests/TestMockedAPIs.java index eaeb30b..67ab5e6 100644 --- a/src/test/java/io/github/ollama4j/unittests/TestMockedAPIs.java +++ b/src/test/java/io/github/ollama4j/unittests/TestMockedAPIs.java @@ -12,7 +12,7 @@ import static org.junit.jupiter.api.Assertions.assertEquals; import static org.junit.jupiter.api.Assertions.fail; import static org.mockito.Mockito.*; -import io.github.ollama4j.OllamaAPI; +import io.github.ollama4j.Ollama; import io.github.ollama4j.exceptions.OllamaException; import io.github.ollama4j.exceptions.RoleNotFoundException; import io.github.ollama4j.models.chat.OllamaChatMessageRole; @@ -36,12 +36,12 @@ import org.mockito.Mockito; class TestMockedAPIs { @Test void testPullModel() { - OllamaAPI ollamaAPI = Mockito.mock(OllamaAPI.class); + Ollama ollama = Mockito.mock(Ollama.class); String model = "llama2"; try { - doNothing().when(ollamaAPI).pullModel(model); - ollamaAPI.pullModel(model); - verify(ollamaAPI, times(1)).pullModel(model); + doNothing().when(ollama).pullModel(model); + ollama.pullModel(model); + verify(ollama, times(1)).pullModel(model); } catch (OllamaException e) { throw new RuntimeException(e); } @@ -49,11 +49,11 @@ class TestMockedAPIs { @Test void testListModels() { - OllamaAPI ollamaAPI = Mockito.mock(OllamaAPI.class); + Ollama ollama = Mockito.mock(Ollama.class); try { - when(ollamaAPI.listModels()).thenReturn(new ArrayList<>()); - ollamaAPI.listModels(); - verify(ollamaAPI, times(1)).listModels(); + when(ollama.listModels()).thenReturn(new ArrayList<>()); + ollama.listModels(); + verify(ollama, times(1)).listModels(); } catch (OllamaException e) { throw new RuntimeException(e); } @@ -61,7 +61,7 @@ class TestMockedAPIs { @Test void testCreateModel() { - OllamaAPI ollamaAPI = Mockito.mock(OllamaAPI.class); + Ollama ollama = Mockito.mock(Ollama.class); CustomModelRequest customModelRequest = CustomModelRequest.builder() .model("mario") @@ -69,9 +69,9 @@ class TestMockedAPIs { .system("You are Mario from Super Mario Bros.") .build(); try { - doNothing().when(ollamaAPI).createModel(customModelRequest); - ollamaAPI.createModel(customModelRequest); - verify(ollamaAPI, times(1)).createModel(customModelRequest); + doNothing().when(ollama).createModel(customModelRequest); + ollama.createModel(customModelRequest); + verify(ollama, times(1)).createModel(customModelRequest); } catch (OllamaException e) { throw new RuntimeException(e); } @@ -79,12 +79,12 @@ class TestMockedAPIs { @Test void testDeleteModel() { - OllamaAPI ollamaAPI = Mockito.mock(OllamaAPI.class); + Ollama ollama = Mockito.mock(Ollama.class); String model = "llama2"; try { - doNothing().when(ollamaAPI).deleteModel(model, true); - ollamaAPI.deleteModel(model, true); - verify(ollamaAPI, times(1)).deleteModel(model, true); + doNothing().when(ollama).deleteModel(model, true); + ollama.deleteModel(model, true); + verify(ollama, times(1)).deleteModel(model, true); } catch (OllamaException e) { throw new RuntimeException(e); } @@ -92,12 +92,12 @@ class TestMockedAPIs { @Test void testGetModelDetails() { - OllamaAPI ollamaAPI = Mockito.mock(OllamaAPI.class); + Ollama ollama = Mockito.mock(Ollama.class); String model = "llama2"; try { - when(ollamaAPI.getModelDetails(model)).thenReturn(new ModelDetail()); - ollamaAPI.getModelDetails(model); - verify(ollamaAPI, times(1)).getModelDetails(model); + when(ollama.getModelDetails(model)).thenReturn(new ModelDetail()); + ollama.getModelDetails(model); + verify(ollama, times(1)).getModelDetails(model); } catch (OllamaException e) { throw new RuntimeException(e); } @@ -105,16 +105,16 @@ class TestMockedAPIs { @Test void testGenerateEmbeddings() { - OllamaAPI ollamaAPI = Mockito.mock(OllamaAPI.class); + Ollama ollama = Mockito.mock(Ollama.class); String model = "llama2"; String prompt = "some prompt text"; try { OllamaEmbedRequest m = new OllamaEmbedRequest(); m.setModel(model); m.setInput(List.of(prompt)); - when(ollamaAPI.embed(m)).thenReturn(new OllamaEmbedResult()); - ollamaAPI.embed(m); - verify(ollamaAPI, times(1)).embed(m); + when(ollama.embed(m)).thenReturn(new OllamaEmbedResult()); + ollama.embed(m); + verify(ollama, times(1)).embed(m); } catch (OllamaException e) { throw new RuntimeException(e); } @@ -122,14 +122,14 @@ class TestMockedAPIs { @Test void testEmbed() { - OllamaAPI ollamaAPI = Mockito.mock(OllamaAPI.class); + Ollama ollama = Mockito.mock(Ollama.class); String model = "llama2"; List inputs = List.of("some prompt text"); try { OllamaEmbedRequest m = new OllamaEmbedRequest(model, inputs); - when(ollamaAPI.embed(m)).thenReturn(new OllamaEmbedResult()); - ollamaAPI.embed(m); - verify(ollamaAPI, times(1)).embed(m); + when(ollama.embed(m)).thenReturn(new OllamaEmbedResult()); + ollama.embed(m); + verify(ollama, times(1)).embed(m); } catch (OllamaException e) { throw new RuntimeException(e); } @@ -137,14 +137,14 @@ class TestMockedAPIs { @Test void testEmbedWithEmbedRequestModel() { - OllamaAPI ollamaAPI = Mockito.mock(OllamaAPI.class); + Ollama ollama = Mockito.mock(Ollama.class); String model = "llama2"; List inputs = List.of("some prompt text"); try { - when(ollamaAPI.embed(new OllamaEmbedRequest(model, inputs))) + when(ollama.embed(new OllamaEmbedRequest(model, inputs))) .thenReturn(new OllamaEmbedResult()); - ollamaAPI.embed(new OllamaEmbedRequest(model, inputs)); - verify(ollamaAPI, times(1)).embed(new OllamaEmbedRequest(model, inputs)); + ollama.embed(new OllamaEmbedRequest(model, inputs)); + verify(ollama, times(1)).embed(new OllamaEmbedRequest(model, inputs)); } catch (OllamaException e) { throw new RuntimeException(e); } @@ -152,7 +152,7 @@ class TestMockedAPIs { @Test void testAsk() { - OllamaAPI ollamaAPI = Mockito.mock(OllamaAPI.class); + Ollama ollama = Mockito.mock(Ollama.class); String model = "llama2"; String prompt = "some prompt text"; OllamaGenerateStreamObserver observer = new OllamaGenerateStreamObserver(null, null); @@ -165,10 +165,9 @@ class TestMockedAPIs { .withThink(false) .withStreaming(false) .build(); - when(ollamaAPI.generate(request, observer)) - .thenReturn(new OllamaResult("", "", 0, 200)); - ollamaAPI.generate(request, observer); - verify(ollamaAPI, times(1)).generate(request, observer); + when(ollama.generate(request, observer)).thenReturn(new OllamaResult("", "", 0, 200)); + ollama.generate(request, observer); + verify(ollama, times(1)).generate(request, observer); } catch (OllamaException e) { throw new RuntimeException(e); } @@ -176,7 +175,7 @@ class TestMockedAPIs { @Test void testAskWithImageFiles() { - OllamaAPI ollamaAPI = Mockito.mock(OllamaAPI.class); + Ollama ollama = Mockito.mock(Ollama.class); String model = "llama2"; String prompt = "some prompt text"; try { @@ -192,9 +191,9 @@ class TestMockedAPIs { .withFormat(null) .build(); OllamaGenerateStreamObserver handler = null; - when(ollamaAPI.generate(request, handler)).thenReturn(new OllamaResult("", "", 0, 200)); - ollamaAPI.generate(request, handler); - verify(ollamaAPI, times(1)).generate(request, handler); + when(ollama.generate(request, handler)).thenReturn(new OllamaResult("", "", 0, 200)); + ollama.generate(request, handler); + verify(ollama, times(1)).generate(request, handler); } catch (Exception e) { throw new RuntimeException(e); } @@ -202,7 +201,7 @@ class TestMockedAPIs { @Test void testAskWithImageURLs() { - OllamaAPI ollamaAPI = Mockito.mock(OllamaAPI.class); + Ollama ollama = Mockito.mock(Ollama.class); String model = "llama2"; String prompt = "some prompt text"; try { @@ -218,9 +217,9 @@ class TestMockedAPIs { .withFormat(null) .build(); OllamaGenerateStreamObserver handler = null; - when(ollamaAPI.generate(request, handler)).thenReturn(new OllamaResult("", "", 0, 200)); - ollamaAPI.generate(request, handler); - verify(ollamaAPI, times(1)).generate(request, handler); + when(ollama.generate(request, handler)).thenReturn(new OllamaResult("", "", 0, 200)); + ollama.generate(request, handler); + verify(ollama, times(1)).generate(request, handler); } catch (OllamaException e) { throw new RuntimeException(e); } catch (IOException e) { @@ -230,56 +229,55 @@ class TestMockedAPIs { @Test void testAskAsync() throws OllamaException { - OllamaAPI ollamaAPI = Mockito.mock(OllamaAPI.class); + Ollama ollama = Mockito.mock(Ollama.class); String model = "llama2"; String prompt = "some prompt text"; - when(ollamaAPI.generateAsync(model, prompt, false, false)) + when(ollama.generateAsync(model, prompt, false, false)) .thenReturn(new OllamaAsyncResultStreamer(null, null, 3)); - ollamaAPI.generateAsync(model, prompt, false, false); - verify(ollamaAPI, times(1)).generateAsync(model, prompt, false, false); + ollama.generateAsync(model, prompt, false, false); + verify(ollama, times(1)).generateAsync(model, prompt, false, false); } @Test void testAddCustomRole() { - OllamaAPI ollamaAPI = mock(OllamaAPI.class); + Ollama ollama = mock(Ollama.class); String roleName = "custom-role"; OllamaChatMessageRole expectedRole = OllamaChatMessageRole.newCustomRole(roleName); - when(ollamaAPI.addCustomRole(roleName)).thenReturn(expectedRole); - OllamaChatMessageRole customRole = ollamaAPI.addCustomRole(roleName); + when(ollama.addCustomRole(roleName)).thenReturn(expectedRole); + OllamaChatMessageRole customRole = ollama.addCustomRole(roleName); assertEquals(expectedRole, customRole); - verify(ollamaAPI, times(1)).addCustomRole(roleName); + verify(ollama, times(1)).addCustomRole(roleName); } @Test void testListRoles() { - OllamaAPI ollamaAPI = Mockito.mock(OllamaAPI.class); + Ollama ollama = Mockito.mock(Ollama.class); OllamaChatMessageRole role1 = OllamaChatMessageRole.newCustomRole("role1"); OllamaChatMessageRole role2 = OllamaChatMessageRole.newCustomRole("role2"); List expectedRoles = List.of(role1, role2); - when(ollamaAPI.listRoles()).thenReturn(expectedRoles); - List actualRoles = ollamaAPI.listRoles(); + when(ollama.listRoles()).thenReturn(expectedRoles); + List actualRoles = ollama.listRoles(); assertEquals(expectedRoles, actualRoles); - verify(ollamaAPI, times(1)).listRoles(); + verify(ollama, times(1)).listRoles(); } @Test void testGetRoleNotFound() { - OllamaAPI ollamaAPI = mock(OllamaAPI.class); + Ollama ollama = mock(Ollama.class); String roleName = "non-existing-role"; try { - when(ollamaAPI.getRole(roleName)) - .thenThrow(new RoleNotFoundException("Role not found")); + when(ollama.getRole(roleName)).thenThrow(new RoleNotFoundException("Role not found")); } catch (RoleNotFoundException exception) { throw new RuntimeException("Failed to run test: testGetRoleNotFound"); } try { - ollamaAPI.getRole(roleName); + ollama.getRole(roleName); fail("Expected RoleNotFoundException not thrown"); } catch (RoleNotFoundException exception) { assertEquals("Role not found", exception.getMessage()); } try { - verify(ollamaAPI, times(1)).getRole(roleName); + verify(ollama, times(1)).getRole(roleName); } catch (RoleNotFoundException exception) { throw new RuntimeException("Failed to run test: testGetRoleNotFound"); } @@ -287,18 +285,18 @@ class TestMockedAPIs { @Test void testGetRoleFound() { - OllamaAPI ollamaAPI = mock(OllamaAPI.class); + Ollama ollama = mock(Ollama.class); String roleName = "existing-role"; OllamaChatMessageRole expectedRole = OllamaChatMessageRole.newCustomRole(roleName); try { - when(ollamaAPI.getRole(roleName)).thenReturn(expectedRole); + when(ollama.getRole(roleName)).thenReturn(expectedRole); } catch (RoleNotFoundException exception) { throw new RuntimeException("Failed to run test: testGetRoleFound"); } try { - OllamaChatMessageRole actualRole = ollamaAPI.getRole(roleName); + OllamaChatMessageRole actualRole = ollama.getRole(roleName); assertEquals(expectedRole, actualRole); - verify(ollamaAPI, times(1)).getRole(roleName); + verify(ollama, times(1)).getRole(roleName); } catch (RoleNotFoundException exception) { throw new RuntimeException("Failed to run test: testGetRoleFound"); } From f114181fe24278ec3333290fc41e17db01847194 Mon Sep 17 00:00:00 2001 From: amithkoujalgi Date: Mon, 29 Sep 2025 09:31:32 +0530 Subject: [PATCH 2/4] Update documentation and refactor code to replace `OllamaAPI` with `Ollama` - Replaced all instances of `OllamaAPI` with `Ollama` in documentation and code examples for consistency. - Enhanced the configuration for handling broken markdown links in Docusaurus. - Updated integration tests and example code snippets to reflect the new class structure. --- docs/METRICS.md | 1 - docs/blog/2025-03-08-blog/index.md | 1 - docs/docs/apis-extras/options-builder.md | 11 ++++++++++- docs/docs/apis-extras/ping.md | 1 - docs/docs/apis-extras/prompt-builder.md | 1 - docs/docs/apis-extras/timeouts.md | 1 - docs/docs/apis-generate/chat-with-tools.md | 8 ++++---- docs/docs/apis-generate/custom-roles.md | 2 -- docs/docs/intro.md | 6 ++---- docs/docusaurus.config.js | 4 +++- .../integrationtests/OllamaIntegrationTest.java | 4 ++-- .../io/github/ollama4j/integrationtests/WithAuth.java | 8 ++++---- 12 files changed, 25 insertions(+), 23 deletions(-) diff --git a/docs/METRICS.md b/docs/METRICS.md index 83dade6..7072810 100644 --- a/docs/METRICS.md +++ b/docs/METRICS.md @@ -18,7 +18,6 @@ The metrics integration provides the following metrics: ```java import io.github.ollama4j.Ollama; -import io.github.ollama4j.OllamaAPI; // Create API instance with metrics enabled Ollama ollama = new Ollama(); diff --git a/docs/blog/2025-03-08-blog/index.md b/docs/blog/2025-03-08-blog/index.md index 637b96b..f520696 100644 --- a/docs/blog/2025-03-08-blog/index.md +++ b/docs/blog/2025-03-08-blog/index.md @@ -337,7 +337,6 @@ import com.couchbase.client.java.Scope; import com.couchbase.client.java.json.JsonObject; import com.couchbase.client.java.query.QueryResult; import io.github.ollama4j.Ollama; -import io.github.ollama4j.OllamaAPI; import io.github.ollama4j.exceptions.OllamaException; import io.github.ollama4j.exceptions.ToolInvocationException; import io.github.ollama4j.tools.OllamaToolsResult; diff --git a/docs/docs/apis-extras/options-builder.md b/docs/docs/apis-extras/options-builder.md index a838950..7873d7a 100644 --- a/docs/docs/apis-extras/options-builder.md +++ b/docs/docs/apis-extras/options-builder.md @@ -65,7 +65,7 @@ public class Main { String host = "http://localhost:11434/"; - OllamaAPI ollama = new OllamaAPI(host); + Ollama ollama = new Ollama(host); Options options = new OptionsBuilder() @@ -74,6 +74,15 @@ public class Main { .setNumGpu(2) .setTemperature(1.5f) .build(); + + OllamaResult result = + ollama.generate( + OllamaGenerateRequestBuilder.builder() + .withModel(model) + .withPrompt("Who are you?") + .withOptions(options) + .build(), + null); } } ``` diff --git a/docs/docs/apis-extras/ping.md b/docs/docs/apis-extras/ping.md index 34153b1..d53db0e 100644 --- a/docs/docs/apis-extras/ping.md +++ b/docs/docs/apis-extras/ping.md @@ -8,7 +8,6 @@ This API lets you check the reachability of Ollama server. ```java import io.github.ollama4j.Ollama; -import io.github.ollama4j.OllamaAPI; public class Main { diff --git a/docs/docs/apis-extras/prompt-builder.md b/docs/docs/apis-extras/prompt-builder.md index 9101e54..bcfa604 100644 --- a/docs/docs/apis-extras/prompt-builder.md +++ b/docs/docs/apis-extras/prompt-builder.md @@ -9,7 +9,6 @@ inferences. ```java import io.github.ollama4j.Ollama; -import io.github.ollama4j.OllamaAPI; import io.github.ollama4j.models.response.OllamaResult; import io.github.ollama4j.types.OllamaModelType; import io.github.ollama4j.utils.OptionsBuilder; diff --git a/docs/docs/apis-extras/timeouts.md b/docs/docs/apis-extras/timeouts.md index eb3354d..ae1204f 100644 --- a/docs/docs/apis-extras/timeouts.md +++ b/docs/docs/apis-extras/timeouts.md @@ -10,7 +10,6 @@ This API lets you set the request timeout for the Ollama client. ```java import io.github.ollama4j.Ollama; -import io.github.ollama4j.OllamaAPI; public class Main { diff --git a/docs/docs/apis-generate/chat-with-tools.md b/docs/docs/apis-generate/chat-with-tools.md index eca5e15..31f91bd 100644 --- a/docs/docs/apis-generate/chat-with-tools.md +++ b/docs/docs/apis-generate/chat-with-tools.md @@ -16,7 +16,7 @@ experience. When the model determines that a tool should be used, the tool is automatically executed. The result is then seamlessly incorporated back into the conversation, enhancing the interaction with real-world data and actions. -The following example demonstrates usage of a simple tool, registered with the `OllamaAPI`, and then used within a chat +The following example demonstrates usage of a simple tool, registered with the `Ollama`, and then used within a chat session. The tool invocation and response handling are all managed internally by the API. @@ -33,7 +33,7 @@ This tool calling can also be done using the streaming API. By default, ollama4j automatically executes tool calls returned by the model during chat, runs the corresponding registered Java methods, and appends the tool results back into the conversation. For some applications, you may want to intercept tool calls and decide yourself when and how to execute them (for example, to queue them, to show a confirmation UI to the user, to run them in a sandbox, or to perform multi‑step orchestration). -To enable this behavior, set the useTools flag to true on your OllamaAPI instance. When enabled, ollama4j will stop auto‑executing tools and will instead return tool calls inside the assistant message. You can then inspect the tool calls and execute them manually. +To enable this behavior, set the useTools flag to true on your Ollama instance. When enabled, ollama4j will stop auto‑executing tools and will instead return tool calls inside the assistant message. You can then inspect the tool calls and execute them manually. Notes: @@ -57,10 +57,10 @@ To use a method as a tool within a chat call, follow these steps: * `java.lang.Boolean` * `java.math.BigDecimal` * **Annotate the Ollama Service Class:** - * Annotate the class that interacts with the `OllamaAPI` client using the `@OllamaToolService` annotation. Reference + * Annotate the class that interacts with the `Ollama` client using the `@OllamaToolService` annotation. Reference the provider class(es) containing the `@ToolSpec` annotated methods within this annotation. * **Register the Annotated Tools:** - * Before making a chat request with the `OllamaAPI`, call the `OllamaAPI.registerAnnotatedTools()` method. This + * Before making a chat request with the `Ollama`, call the `Ollama.registerAnnotatedTools()` method. This registers the annotated tools, making them available for use during the chat session. Let's try an example. Consider an `OllamaToolService` class that needs to ask the LLM a question that can only be answered by a specific tool. diff --git a/docs/docs/apis-generate/custom-roles.md b/docs/docs/apis-generate/custom-roles.md index 9858792..bb9e6de 100644 --- a/docs/docs/apis-generate/custom-roles.md +++ b/docs/docs/apis-generate/custom-roles.md @@ -17,7 +17,6 @@ _Base roles are `SYSTEM`, `USER`, `ASSISTANT`, `TOOL`._ ```java import io.github.ollama4j.Ollama; -import io.github.ollama4j.OllamaAPI; import io.github.ollama4j.models.chat.OllamaChatMessageRole; public class Main { @@ -52,7 +51,6 @@ public class Main { ```java import io.github.ollama4j.Ollama; -import io.github.ollama4j.OllamaAPI; import io.github.ollama4j.models.chat.OllamaChatMessageRole; public class Main { diff --git a/docs/docs/intro.md b/docs/docs/intro.md index f237a31..80749ff 100644 --- a/docs/docs/intro.md +++ b/docs/docs/intro.md @@ -113,9 +113,8 @@ Create a new Java class in your project and add this code. ```java import io.github.ollama4j.Ollama; -import io.github.ollama4j.OllamaAPI; -public class OllamaAPITest { +public class OllamaTest { public static void main(String[] args) { Ollama ollama = new Ollama(); @@ -132,9 +131,8 @@ Specify a different Ollama host that you want to connect to. ```java import io.github.ollama4j.Ollama; -import io.github.ollama4j.OllamaAPI; -public class OllamaAPITest { +public class OllamaTest { public static void main(String[] args) { String host = "http://localhost:11434/"; diff --git a/docs/docusaurus.config.js b/docs/docusaurus.config.js index 8d3eddc..a7363ad 100644 --- a/docs/docusaurus.config.js +++ b/docs/docusaurus.config.js @@ -24,7 +24,6 @@ const config = { projectName: 'ollama4j', // Usually your repo name. onBrokenLinks: 'throw', - onBrokenMarkdownLinks: 'warn', // Even if you don't use internationalization, you can use this field to set // useful metadata like html lang. For example, if your site is Chinese, you @@ -175,6 +174,9 @@ const config = { }), markdown: { mermaid: true, + hooks: { + onBrokenMarkdownLinks: 'warn' + } }, themes: ['@docusaurus/theme-mermaid'] }; diff --git a/src/test/java/io/github/ollama4j/integrationtests/OllamaIntegrationTest.java b/src/test/java/io/github/ollama4j/integrationtests/OllamaIntegrationTest.java index 53e0ef5..7e8ea90 100644 --- a/src/test/java/io/github/ollama4j/integrationtests/OllamaIntegrationTest.java +++ b/src/test/java/io/github/ollama4j/integrationtests/OllamaIntegrationTest.java @@ -58,9 +58,9 @@ class OllamaIntegrationTest { private static final String TOOLS_MODEL = "mistral:7b"; /** - * Initializes the OllamaAPI instance for integration tests. + * Initializes the Ollama instance for integration tests. * - *

This method sets up the OllamaAPI client, either using an external Ollama host (if + *

This method sets up the Ollama client, either using an external Ollama host (if * environment variables are set) or by starting a Testcontainers-based Ollama instance. It also * configures request timeout and model pull retry settings. */ diff --git a/src/test/java/io/github/ollama4j/integrationtests/WithAuth.java b/src/test/java/io/github/ollama4j/integrationtests/WithAuth.java index fe22ea3..2d8a66c 100644 --- a/src/test/java/io/github/ollama4j/integrationtests/WithAuth.java +++ b/src/test/java/io/github/ollama4j/integrationtests/WithAuth.java @@ -88,7 +88,7 @@ public class WithAuth { + "→ Proxy URL: {}", ollamaUrl, nginxUrl); - LOG.info("OllamaAPI initialized with bearer auth token: {}", BEARER_AUTH_TOKEN); + LOG.info("Ollama initialized with bearer auth token: {}", BEARER_AUTH_TOKEN); } private static OllamaContainer createOllamaContainer() { @@ -155,9 +155,9 @@ public class WithAuth { try { assertTrue( api.ping(), - "Expected OllamaAPI to successfully ping through NGINX with valid auth token."); + "Expected Ollama to successfully ping through NGINX with valid auth token."); } catch (Exception e) { - fail("Exception occurred while pinging OllamaAPI through NGINX: " + e.getMessage(), e); + fail("Exception occurred while pinging Ollama through NGINX: " + e.getMessage(), e); } } @@ -168,7 +168,7 @@ public class WithAuth { try { assertFalse( api.ping(), - "Expected OllamaAPI ping to fail through NGINX with an invalid auth token."); + "Expected Ollama ping to fail through NGINX with an invalid auth token."); } catch (Exception e) { // If an exception is thrown, that's also an expected failure for a wrong token // (e.g., OllamaBaseException or IOException) From 501c35fa44332ea86750c8723c07e2a5807c79b9 Mon Sep 17 00:00:00 2001 From: amithkoujalgi Date: Mon, 29 Sep 2025 10:36:13 +0530 Subject: [PATCH 3/4] Refactor integration test targets in Makefile and update workflow - Renamed integration test targets in the Makefile for clarity: `integration-tests` to `integration-tests-all` and added `integration-tests-basic`. - Updated GitHub Actions workflow to run the new `integration-tests-basic` target. - Cleaned up the `WithAuth` test class by removing unused imports and simplifying method signatures. --- .github/workflows/run-tests.yml | 2 +- Makefile | 10 +++++++--- .../io/github/ollama4j/integrationtests/WithAuth.java | 5 +---- 3 files changed, 9 insertions(+), 8 deletions(-) diff --git a/.github/workflows/run-tests.yml b/.github/workflows/run-tests.yml index 4583cb9..c688063 100644 --- a/.github/workflows/run-tests.yml +++ b/.github/workflows/run-tests.yml @@ -48,7 +48,7 @@ jobs: run: mvn clean test -Punit-tests - name: Run integration tests - run: mvn clean verify -Pintegration-tests + run: mvn clean verify -Pintegration-tests-basic env: USE_EXTERNAL_OLLAMA_HOST: "true" OLLAMA_HOST: "http://localhost:11434" \ No newline at end of file diff --git a/Makefile b/Makefile index 7b5ad0c..b134b29 100644 --- a/Makefile +++ b/Makefile @@ -26,12 +26,16 @@ unit-tests: apply-formatting @echo "\033[0;34mRunning unit tests...\033[0m" @mvn clean test -Punit-tests -integration-tests: apply-formatting - @echo "\033[0;34mRunning integration tests (local)...\033[0m" +integration-tests-all: apply-formatting + @echo "\033[0;34mRunning integration tests (local - all)...\033[0m" @export USE_EXTERNAL_OLLAMA_HOST=false && mvn clean verify -Pintegration-tests +integration-tests-basic: apply-formatting + @echo "\033[0;34mRunning integration tests (local - basic)...\033[0m" + @export USE_EXTERNAL_OLLAMA_HOST=false && mvn clean verify -Pintegration-tests -Dit.test=WithAuth + integration-tests-remote: apply-formatting - @echo "\033[0;34mRunning integration tests (remote)...\033[0m" + @echo "\033[0;34mRunning integration tests (remote - all)...\033[0m" @export USE_EXTERNAL_OLLAMA_HOST=true && export OLLAMA_HOST=http://192.168.29.229:11434 && mvn clean verify -Pintegration-tests -Dgpg.skip=true doxygen: diff --git a/src/test/java/io/github/ollama4j/integrationtests/WithAuth.java b/src/test/java/io/github/ollama4j/integrationtests/WithAuth.java index 2d8a66c..091830e 100644 --- a/src/test/java/io/github/ollama4j/integrationtests/WithAuth.java +++ b/src/test/java/io/github/ollama4j/integrationtests/WithAuth.java @@ -22,7 +22,6 @@ import io.github.ollama4j.utils.OptionsBuilder; import java.io.File; import java.io.FileWriter; import java.io.IOException; -import java.net.URISyntaxException; import java.time.Duration; import java.util.Collections; import java.util.HashMap; @@ -174,14 +173,12 @@ public class WithAuth { // (e.g., OllamaBaseException or IOException) // Optionally, you can assert the type/message of the exception if needed // For now, we treat any exception as a pass for this negative test - return; } } @Test @Order(2) - void testAskModelWithStructuredOutput() - throws OllamaException, IOException, InterruptedException, URISyntaxException { + void testAskModelWithStructuredOutput() throws OllamaException, IOException { api.setBearerAuth(BEARER_AUTH_TOKEN); String model = GENERAL_PURPOSE_MODEL; api.pullModel(model); From fd18a247d7be60a790a61bcdc014146a47bca13c Mon Sep 17 00:00:00 2001 From: amithkoujalgi Date: Mon, 29 Sep 2025 11:15:21 +0530 Subject: [PATCH 4/4] Update GitHub Actions workflow to use Makefile for test execution - Replaced Maven commands with Makefile targets for running unit and integration tests in the GitHub Actions workflow. - Updated the commands to `make unit-tests` and `make integration-tests-basic` for improved consistency and maintainability. --- .github/workflows/run-tests.yml | 4 ++-- 1 file changed, 2 insertions(+), 2 deletions(-) diff --git a/.github/workflows/run-tests.yml b/.github/workflows/run-tests.yml index c688063..d152333 100644 --- a/.github/workflows/run-tests.yml +++ b/.github/workflows/run-tests.yml @@ -45,10 +45,10 @@ jobs: settings-path: ${{ github.workspace }} - name: Run unit tests - run: mvn clean test -Punit-tests + run: make unit-tests - name: Run integration tests - run: mvn clean verify -Pintegration-tests-basic + run: make integration-tests-basic env: USE_EXTERNAL_OLLAMA_HOST: "true" OLLAMA_HOST: "http://localhost:11434" \ No newline at end of file