forked from Mirror/ollama4j
		
	Compare commits
	
		
			19 Commits
		
	
	
		
	
	| Author | SHA1 | Date | |
|---|---|---|---|
|   | b57fc1f818 | ||
|   | 01c5a8f07f | ||
|   | 243b8a3747 | ||
|   | 987fce7f07 | ||
|   | 657593be09 | ||
|   | 0afba7e3e3 | ||
|   | ac00bb9029 | ||
|   | 67cb444d82 | ||
|   | 1914a29163 | ||
|   | 11201bc7c7 | ||
|   | 3a8b5257c0 | ||
|   | 00bb4e92dc | ||
|   | 7481c2ba0e | ||
|   | 9d336e257c | ||
|   | 2027171cb9 | ||
|   | e06baf0d29 | ||
|   | 5d6a68a5bb | ||
|   | 41a5bb70bf | ||
|   | c2ec62ba08 | 
							
								
								
									
										72
									
								
								README.md
									
									
									
									
									
								
							
							
						
						
									
										72
									
								
								README.md
									
									
									
									
									
								
							| @@ -2,8 +2,33 @@ | ||||
|  | ||||
| <img src='https://raw.githubusercontent.com/amithkoujalgi/ollama4j/65a9d526150da8fcd98e2af6a164f055572bf722/ollama4j.jpeg' width='100' alt="ollama4j-icon"> | ||||
|  | ||||
| A Java library (wrapper/binding) | ||||
| for [Ollama](https://github.com/jmorganca/ollama/blob/main/docs/api.md) APIs. | ||||
| A Java library (wrapper/binding) for [Ollama](https://ollama.ai/) server. | ||||
|  | ||||
| Find more details on the [website](https://amithkoujalgi.github.io/ollama4j/). | ||||
|  | ||||
|  | ||||
|  | ||||
|  | ||||
|  | ||||
|  | ||||
|  | ||||
|  | ||||
|  | ||||
|  | ||||
|  | ||||
|  | ||||
| ## Table of Contents | ||||
|  | ||||
| - [How does it work?](#how-does-it-work) | ||||
| - [Requirements](#requirements) | ||||
| - [Installation](#installation) | ||||
| - [API Spec](#api-spec) | ||||
| - [Demo APIs](#try-out-the-apis-with-ollama-server) | ||||
| - [Development](#development) | ||||
| - [Contributions](#get-involved) | ||||
| - [References](#references) | ||||
|  | ||||
| #### How does it work? | ||||
|  | ||||
| ```mermaid | ||||
|   flowchart LR | ||||
| @@ -17,39 +42,19 @@ for [Ollama](https://github.com/jmorganca/ollama/blob/main/docs/api.md) APIs. | ||||
|     end | ||||
| ``` | ||||
|  | ||||
|  | ||||
|  | ||||
|  | ||||
|  | ||||
|  | ||||
|  | ||||
|  | ||||
|  | ||||
|  | ||||
|  | ||||
|  | ||||
| ## Table of Contents | ||||
|  | ||||
| - [Requirements](#requirements) | ||||
| - [Installation](#installation) | ||||
| - [API Spec](#api-spec) | ||||
| - [Demo APIs](#try-out-the-apis-with-ollama-server) | ||||
| - [Development](#development) | ||||
| - [Contributions](#get-involved) | ||||
|  | ||||
| #### Requirements | ||||
|  | ||||
|  | ||||
|  | ||||
|  | ||||
| [![][ollama-shield]][ollama] Or  [![][ollama-docker-shield]][ollama-docker] | ||||
| [![][ollama-shield]][ollama] **Or** [![][ollama-docker-shield]][ollama-docker] | ||||
|  | ||||
| [ollama]: https://ollama.ai/ | ||||
|  | ||||
| [ollama-shield]: https://img.shields.io/badge/Ollama-Local_Installation-blue.svg?style=for-the-badge&labelColor=gray | ||||
| [ollama-shield]: https://img.shields.io/badge/Ollama-Local_Installation-blue.svg?style=just-the-message&labelColor=gray | ||||
|  | ||||
| [ollama-docker]: https://hub.docker.com/r/ollama/ollama | ||||
|  | ||||
| [ollama-docker-shield]: https://img.shields.io/badge/Ollama-Docker-blue.svg?style=for-the-badge&labelColor=gray | ||||
| [ollama-docker-shield]: https://img.shields.io/badge/Ollama-Docker-blue.svg?style=just-the-message&labelColor=gray | ||||
|  | ||||
| #### Installation | ||||
|  | ||||
| @@ -60,21 +65,23 @@ In your Maven project, add this dependency: | ||||
| <dependency> | ||||
|     <groupId>io.github.amithkoujalgi</groupId> | ||||
|     <artifactId>ollama4j</artifactId> | ||||
|     <version>1.0.20</version> | ||||
|     <version>1.0.29</version> | ||||
| </dependency> | ||||
| ``` | ||||
|  | ||||
| Latest release:  | ||||
| Latest release: | ||||
|  | ||||
|  | ||||
|  | ||||
| [![][lib-shield]][lib] | ||||
|  | ||||
| [lib]: https://central.sonatype.com/artifact/io.github.amithkoujalgi/ollama4j | ||||
|  | ||||
| [lib-shield]: https://img.shields.io/badge/ollama4j-get_latest_version-blue.svg?style=for-the-badge&labelColor=gray | ||||
| [lib-shield]: https://img.shields.io/badge/ollama4j-get_latest_version-blue.svg?style=just-the-message&labelColor=gray | ||||
|  | ||||
| #### API Spec | ||||
|  | ||||
| Find the full `Javadoc` (API specifications) [here](https://amithkoujalgi.github.io/ollama4j/). | ||||
| Find the full API specifications on the [website](https://amithkoujalgi.github.io/ollama4j/). | ||||
|  | ||||
| #### Development | ||||
|  | ||||
| @@ -115,6 +122,7 @@ Actions CI workflow. | ||||
| - [x] Use lombok | ||||
| - [x] Update request body creation with Java objects | ||||
| - [ ] Async APIs for images | ||||
| - [ ] Add custom headers to requests | ||||
| - [ ] Add additional params for `ask` APIs such as: | ||||
|     - `options`: additional model parameters for the Modelfile such as `temperature` | ||||
|     - `system`: system prompt to (overrides what is defined in the Modelfile) | ||||
| @@ -136,3 +144,7 @@ of contribution is much appreciated. | ||||
|  | ||||
| The nomenclature and the icon have been adopted from the incredible [Ollama](https://ollama.ai/) | ||||
| project. | ||||
|  | ||||
| ### References | ||||
|  | ||||
| - [Ollama REST APIs](https://github.com/jmorganca/ollama/blob/main/docs/api.md) | ||||
| @@ -3,6 +3,6 @@ | ||||
|   "position": 10, | ||||
|   "link": { | ||||
|     "type": "generated-index", | ||||
|     "description": "Specs of APIs and their usage." | ||||
|     "description": "Details of APIs to interact with LLMs." | ||||
|   } | ||||
| } | ||||
|   | ||||
							
								
								
									
										8
									
								
								docs/docs/apis-extras/_category_.json
									
									
									
									
									
										Normal file
									
								
							
							
						
						
									
										8
									
								
								docs/docs/apis-extras/_category_.json
									
									
									
									
									
										Normal file
									
								
							| @@ -0,0 +1,8 @@ | ||||
| { | ||||
|   "label": "APIs - Extras", | ||||
|   "position": 10, | ||||
|   "link": { | ||||
|     "type": "generated-index", | ||||
|     "description": "Details of APIs to handle bunch of extra stuff." | ||||
|   } | ||||
| } | ||||
							
								
								
									
										24
									
								
								docs/docs/apis-extras/basic-auth.md
									
									
									
									
									
										Normal file
									
								
							
							
						
						
									
										24
									
								
								docs/docs/apis-extras/basic-auth.md
									
									
									
									
									
										Normal file
									
								
							| @@ -0,0 +1,24 @@ | ||||
| --- | ||||
| sidebar_position: 2 | ||||
| --- | ||||
|  | ||||
| # Set Basic Authentication | ||||
|  | ||||
| This API lets you set the basic authentication for the Ollama client. This would help in scenarios where | ||||
| 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 | ||||
| public class Main { | ||||
|  | ||||
|     public static void main(String[] args) { | ||||
|  | ||||
|         String host = "http://localhost:11434/"; | ||||
|  | ||||
|         OllamaAPI ollamaAPI = new OllamaAPI(host); | ||||
|  | ||||
|         ollamaAPI.setBasicAuth("username", "password"); | ||||
|     } | ||||
| } | ||||
| ``` | ||||
							
								
								
									
										20
									
								
								docs/docs/apis-extras/ping.md
									
									
									
									
									
										Normal file
									
								
							
							
						
						
									
										20
									
								
								docs/docs/apis-extras/ping.md
									
									
									
									
									
										Normal file
									
								
							| @@ -0,0 +1,20 @@ | ||||
| --- | ||||
| sidebar_position: 3 | ||||
| --- | ||||
|  | ||||
| # Ping | ||||
|  | ||||
| This API lets you check the reachability of Ollama server. | ||||
|  | ||||
| ```java | ||||
| public class Main { | ||||
|  | ||||
|     public static void main(String[] args) { | ||||
|         String host = "http://localhost:11434/"; | ||||
|          | ||||
|         OllamaAPI ollamaAPI = new OllamaAPI(host); | ||||
|          | ||||
|         ollamaAPI.ping(); | ||||
|     } | ||||
| } | ||||
| ``` | ||||
							
								
								
									
										21
									
								
								docs/docs/apis-extras/request-timeout.md
									
									
									
									
									
										Normal file
									
								
							
							
						
						
									
										21
									
								
								docs/docs/apis-extras/request-timeout.md
									
									
									
									
									
										Normal file
									
								
							| @@ -0,0 +1,21 @@ | ||||
| --- | ||||
| sidebar_position: 2 | ||||
| --- | ||||
|  | ||||
| # Set Request Timeout | ||||
|  | ||||
| This API lets you set the request timeout for the Ollama client. | ||||
|  | ||||
| ```java | ||||
| public class Main { | ||||
|  | ||||
|   public static void main(String[] args) { | ||||
|  | ||||
|     String host = "http://localhost:11434/"; | ||||
|  | ||||
|     OllamaAPI ollamaAPI = new OllamaAPI(host); | ||||
|  | ||||
|     ollamaAPI.setRequestTimeoutSeconds(10); | ||||
|   } | ||||
| } | ||||
| ``` | ||||
							
								
								
									
										23
									
								
								docs/docs/apis-extras/verbosity.md
									
									
									
									
									
										Normal file
									
								
							
							
						
						
									
										23
									
								
								docs/docs/apis-extras/verbosity.md
									
									
									
									
									
										Normal file
									
								
							| @@ -0,0 +1,23 @@ | ||||
| --- | ||||
| sidebar_position: 1 | ||||
| --- | ||||
|  | ||||
| # Set Verbosity | ||||
|  | ||||
| This API lets you set the verbosity of the Ollama client. | ||||
|  | ||||
| ## Try asking a question about the model. | ||||
|  | ||||
| ```java | ||||
| public class Main { | ||||
|  | ||||
|     public static void main(String[] args) { | ||||
|  | ||||
|         String host = "http://localhost:11434/"; | ||||
|  | ||||
|         OllamaAPI ollamaAPI = new OllamaAPI(host); | ||||
|  | ||||
|         ollamaAPI.setVerbose(true); | ||||
|     } | ||||
| } | ||||
| ``` | ||||
| @@ -3,6 +3,6 @@ | ||||
|   "position": 4, | ||||
|   "link": { | ||||
|     "type": "generated-index", | ||||
|     "description": "Specs of APIs and their usage." | ||||
|     "description": "Details of APIs to manage LLMs." | ||||
|   } | ||||
| } | ||||
|   | ||||
							
								
								
									
										4
									
								
								pom.xml
									
									
									
									
									
								
							
							
						
						
									
										4
									
								
								pom.xml
									
									
									
									
									
								
							| @@ -4,7 +4,7 @@ | ||||
|  | ||||
|     <groupId>io.github.amithkoujalgi</groupId> | ||||
|     <artifactId>ollama4j</artifactId> | ||||
|     <version>1.0.28</version> | ||||
|     <version>1.0.33</version> | ||||
|  | ||||
|     <name>Ollama4j</name> | ||||
|     <description>Java library for interacting with Ollama API.</description> | ||||
| @@ -39,7 +39,7 @@ | ||||
|         <connection>scm:git:git@github.com:amithkoujalgi/ollama4j.git</connection> | ||||
|         <developerConnection>scm:git:https://github.com/amithkoujalgi/ollama4j.git</developerConnection> | ||||
|         <url>https://github.com/amithkoujalgi/ollama4j</url> | ||||
|         <tag>v1.0.28</tag> | ||||
|         <tag>v1.0.33</tag> | ||||
|     </scm> | ||||
|  | ||||
|     <build> | ||||
|   | ||||
| @@ -37,6 +37,7 @@ public class OllamaAPI { | ||||
|   private final String host; | ||||
|   private long requestTimeoutSeconds = 3; | ||||
|   private boolean verbose = true; | ||||
|   private BasicAuth basicAuth; | ||||
|  | ||||
|   /** | ||||
|    * Instantiates the Ollama API. | ||||
| @@ -51,6 +52,11 @@ public class OllamaAPI { | ||||
|     } | ||||
|   } | ||||
|  | ||||
|   /** | ||||
|    * Set request timeout in seconds. Default is 3 seconds. | ||||
|    * | ||||
|    * @param requestTimeoutSeconds the request timeout in seconds | ||||
|    */ | ||||
|   public void setRequestTimeoutSeconds(long requestTimeoutSeconds) { | ||||
|     this.requestTimeoutSeconds = requestTimeoutSeconds; | ||||
|   } | ||||
| @@ -64,6 +70,16 @@ public class OllamaAPI { | ||||
|     this.verbose = verbose; | ||||
|   } | ||||
|  | ||||
|   /** | ||||
|    * Set basic authentication for accessing Ollama server that's behind a reverse-proxy/gateway. | ||||
|    * | ||||
|    * @param username the username | ||||
|    * @param password the password | ||||
|    */ | ||||
|   public void setBasicAuth(String username, String password) { | ||||
|     this.basicAuth = new BasicAuth(username, password); | ||||
|   } | ||||
|  | ||||
|   /** | ||||
|    * API to check the reachability of Ollama server. | ||||
|    * | ||||
| @@ -75,11 +91,9 @@ public class OllamaAPI { | ||||
|     HttpRequest httpRequest = null; | ||||
|     try { | ||||
|       httpRequest = | ||||
|           HttpRequest.newBuilder() | ||||
|               .uri(new URI(url)) | ||||
|           getRequestBuilderDefault(new URI(url)) | ||||
|               .header("Accept", "application/json") | ||||
|               .header("Content-type", "application/json") | ||||
|               .timeout(Duration.ofSeconds(requestTimeoutSeconds)) | ||||
|               .GET() | ||||
|               .build(); | ||||
|     } catch (URISyntaxException e) { | ||||
| @@ -107,11 +121,9 @@ public class OllamaAPI { | ||||
|     String url = this.host + "/api/tags"; | ||||
|     HttpClient httpClient = HttpClient.newHttpClient(); | ||||
|     HttpRequest httpRequest = | ||||
|         HttpRequest.newBuilder() | ||||
|             .uri(new URI(url)) | ||||
|         getRequestBuilderDefault(new URI(url)) | ||||
|             .header("Accept", "application/json") | ||||
|             .header("Content-type", "application/json") | ||||
|             .timeout(Duration.ofSeconds(requestTimeoutSeconds)) | ||||
|             .GET() | ||||
|             .build(); | ||||
|     HttpResponse<String> response = | ||||
| @@ -138,12 +150,10 @@ public class OllamaAPI { | ||||
|     String url = this.host + "/api/pull"; | ||||
|     String jsonData = new ModelRequest(modelName).toString(); | ||||
|     HttpRequest request = | ||||
|         HttpRequest.newBuilder() | ||||
|             .uri(new URI(url)) | ||||
|         getRequestBuilderDefault(new URI(url)) | ||||
|             .POST(HttpRequest.BodyPublishers.ofString(jsonData)) | ||||
|             .header("Accept", "application/json") | ||||
|             .header("Content-type", "application/json") | ||||
|             .timeout(Duration.ofSeconds(requestTimeoutSeconds)) | ||||
|             .build(); | ||||
|     HttpClient client = HttpClient.newHttpClient(); | ||||
|     HttpResponse<InputStream> response = | ||||
| @@ -174,15 +184,13 @@ public class OllamaAPI { | ||||
|    * @return the model details | ||||
|    */ | ||||
|   public ModelDetail getModelDetails(String modelName) | ||||
|       throws IOException, OllamaBaseException, InterruptedException { | ||||
|       throws IOException, OllamaBaseException, InterruptedException, URISyntaxException { | ||||
|     String url = this.host + "/api/show"; | ||||
|     String jsonData = new ModelRequest(modelName).toString(); | ||||
|     HttpRequest request = | ||||
|         HttpRequest.newBuilder() | ||||
|             .uri(URI.create(url)) | ||||
|         getRequestBuilderDefault(new URI(url)) | ||||
|             .header("Accept", "application/json") | ||||
|             .header("Content-type", "application/json") | ||||
|             .timeout(Duration.ofSeconds(requestTimeoutSeconds)) | ||||
|             .POST(HttpRequest.BodyPublishers.ofString(jsonData)) | ||||
|             .build(); | ||||
|     HttpClient client = HttpClient.newHttpClient(); | ||||
| @@ -204,15 +212,13 @@ public class OllamaAPI { | ||||
|    * @param modelFilePath the path to model file that exists on the Ollama server. | ||||
|    */ | ||||
|   public void createModelWithFilePath(String modelName, String modelFilePath) | ||||
|       throws IOException, InterruptedException, OllamaBaseException { | ||||
|       throws IOException, InterruptedException, OllamaBaseException, URISyntaxException { | ||||
|     String url = this.host + "/api/create"; | ||||
|     String jsonData = new CustomModelFilePathRequest(modelName, modelFilePath).toString(); | ||||
|     HttpRequest request = | ||||
|         HttpRequest.newBuilder() | ||||
|             .uri(URI.create(url)) | ||||
|         getRequestBuilderDefault(new URI(url)) | ||||
|             .header("Accept", "application/json") | ||||
|             .header("Content-Type", "application/json") | ||||
|             .timeout(Duration.ofSeconds(requestTimeoutSeconds)) | ||||
|             .POST(HttpRequest.BodyPublishers.ofString(jsonData, StandardCharsets.UTF_8)) | ||||
|             .build(); | ||||
|     HttpClient client = HttpClient.newHttpClient(); | ||||
| @@ -240,15 +246,13 @@ public class OllamaAPI { | ||||
|    * @param modelFileContents the path to model file that exists on the Ollama server. | ||||
|    */ | ||||
|   public void createModelWithModelFileContents(String modelName, String modelFileContents) | ||||
|       throws IOException, InterruptedException, OllamaBaseException { | ||||
|       throws IOException, InterruptedException, OllamaBaseException, URISyntaxException { | ||||
|     String url = this.host + "/api/create"; | ||||
|     String jsonData = new CustomModelFileContentsRequest(modelName, modelFileContents).toString(); | ||||
|     HttpRequest request = | ||||
|         HttpRequest.newBuilder() | ||||
|             .uri(URI.create(url)) | ||||
|         getRequestBuilderDefault(new URI(url)) | ||||
|             .header("Accept", "application/json") | ||||
|             .header("Content-Type", "application/json") | ||||
|             .timeout(Duration.ofSeconds(requestTimeoutSeconds)) | ||||
|             .POST(HttpRequest.BodyPublishers.ofString(jsonData, StandardCharsets.UTF_8)) | ||||
|             .build(); | ||||
|     HttpClient client = HttpClient.newHttpClient(); | ||||
| @@ -270,20 +274,17 @@ public class OllamaAPI { | ||||
|    * Delete a model from Ollama server. | ||||
|    * | ||||
|    * @param modelName the name of the model to be deleted. | ||||
|    * @param ignoreIfNotPresent - ignore errors if the specified model is not present on Ollama | ||||
|    *     server. | ||||
|    * @param ignoreIfNotPresent ignore errors if the specified model is not present on Ollama server. | ||||
|    */ | ||||
|   public void deleteModel(String modelName, boolean ignoreIfNotPresent) | ||||
|       throws IOException, InterruptedException, OllamaBaseException { | ||||
|       throws IOException, InterruptedException, OllamaBaseException, URISyntaxException { | ||||
|     String url = this.host + "/api/delete"; | ||||
|     String jsonData = new ModelRequest(modelName).toString(); | ||||
|     HttpRequest request = | ||||
|         HttpRequest.newBuilder() | ||||
|             .uri(URI.create(url)) | ||||
|         getRequestBuilderDefault(new URI(url)) | ||||
|             .method("DELETE", HttpRequest.BodyPublishers.ofString(jsonData, StandardCharsets.UTF_8)) | ||||
|             .header("Accept", "application/json") | ||||
|             .header("Content-type", "application/json") | ||||
|             .timeout(Duration.ofSeconds(requestTimeoutSeconds)) | ||||
|             .build(); | ||||
|     HttpClient client = HttpClient.newHttpClient(); | ||||
|     HttpResponse<String> response = client.send(request, HttpResponse.BodyHandlers.ofString()); | ||||
| @@ -306,17 +307,14 @@ public class OllamaAPI { | ||||
|    */ | ||||
|   public List<Double> generateEmbeddings(String model, String prompt) | ||||
|       throws IOException, InterruptedException, OllamaBaseException { | ||||
|     String url = this.host + "/api/embeddings"; | ||||
|     URI uri = URI.create(this.host + "/api/embeddings"); | ||||
|     String jsonData = new ModelEmbeddingsRequest(model, prompt).toString(); | ||||
|     HttpClient httpClient = HttpClient.newHttpClient(); | ||||
|     HttpRequest request = | ||||
|         HttpRequest.newBuilder() | ||||
|             .uri(URI.create(url)) | ||||
|     HttpRequest.Builder requestBuilder = | ||||
|         getRequestBuilderDefault(uri) | ||||
|             .header("Accept", "application/json") | ||||
|             .header("Content-type", "application/json") | ||||
|             .timeout(Duration.ofSeconds(requestTimeoutSeconds)) | ||||
|             .POST(HttpRequest.BodyPublishers.ofString(jsonData)) | ||||
|             .build(); | ||||
|             .POST(HttpRequest.BodyPublishers.ofString(jsonData)); | ||||
|     HttpRequest request = requestBuilder.build(); | ||||
|     HttpResponse<String> response = httpClient.send(request, HttpResponse.BodyHandlers.ofString()); | ||||
|     int statusCode = response.statusCode(); | ||||
|     String responseBody = response.body(); | ||||
| @@ -333,12 +331,12 @@ public class OllamaAPI { | ||||
|    * Ask a question to a model running on Ollama server. This is a sync/blocking call. | ||||
|    * | ||||
|    * @param model the ollama model to ask the question to | ||||
|    * @param promptText the prompt/question text | ||||
|    * @return OllamaResult - that includes response text and time taken for response | ||||
|    * @param prompt the prompt/question text | ||||
|    * @return OllamaResult that includes response text and time taken for response | ||||
|    */ | ||||
|   public OllamaResult ask(String model, String promptText) | ||||
|   public OllamaResult ask(String model, String prompt) | ||||
|       throws OllamaBaseException, IOException, InterruptedException { | ||||
|     OllamaRequestModel ollamaRequestModel = new OllamaRequestModel(model, promptText); | ||||
|     OllamaRequestModel ollamaRequestModel = new OllamaRequestModel(model, prompt); | ||||
|     return askSync(ollamaRequestModel); | ||||
|   } | ||||
|  | ||||
| @@ -348,15 +346,16 @@ public class OllamaAPI { | ||||
|    * async/non-blocking call. | ||||
|    * | ||||
|    * @param model the ollama model to ask the question to | ||||
|    * @param promptText the prompt/question text | ||||
|    * @param prompt the prompt/question text | ||||
|    * @return the ollama async result callback handle | ||||
|    */ | ||||
|   public OllamaAsyncResultCallback askAsync(String model, String promptText) { | ||||
|     OllamaRequestModel ollamaRequestModel = new OllamaRequestModel(model, promptText); | ||||
|     HttpClient httpClient = HttpClient.newHttpClient(); | ||||
|   public OllamaAsyncResultCallback askAsync(String model, String prompt) { | ||||
|     OllamaRequestModel ollamaRequestModel = new OllamaRequestModel(model, prompt); | ||||
|  | ||||
|     URI uri = URI.create(this.host + "/api/generate"); | ||||
|     OllamaAsyncResultCallback ollamaAsyncResultCallback = | ||||
|         new OllamaAsyncResultCallback(httpClient, uri, ollamaRequestModel, requestTimeoutSeconds); | ||||
|         new OllamaAsyncResultCallback( | ||||
|             getRequestBuilderDefault(uri), ollamaRequestModel, requestTimeoutSeconds); | ||||
|     ollamaAsyncResultCallback.start(); | ||||
|     return ollamaAsyncResultCallback; | ||||
|   } | ||||
| @@ -366,17 +365,17 @@ public class OllamaAPI { | ||||
|    * sync/blocking call. | ||||
|    * | ||||
|    * @param model the ollama model to ask the question to | ||||
|    * @param promptText the prompt/question text | ||||
|    * @param prompt the prompt/question text | ||||
|    * @param imageFiles the list of image files to use for the question | ||||
|    * @return OllamaResult - that includes response text and time taken for response | ||||
|    * @return OllamaResult that includes response text and time taken for response | ||||
|    */ | ||||
|   public OllamaResult askWithImageFiles(String model, String promptText, List<File> imageFiles) | ||||
|   public OllamaResult askWithImageFiles(String model, String prompt, List<File> imageFiles) | ||||
|       throws OllamaBaseException, IOException, InterruptedException { | ||||
|     List<String> images = new ArrayList<>(); | ||||
|     for (File imageFile : imageFiles) { | ||||
|       images.add(encodeFileToBase64(imageFile)); | ||||
|     } | ||||
|     OllamaRequestModel ollamaRequestModel = new OllamaRequestModel(model, promptText, images); | ||||
|     OllamaRequestModel ollamaRequestModel = new OllamaRequestModel(model, prompt, images); | ||||
|     return askSync(ollamaRequestModel); | ||||
|   } | ||||
|  | ||||
| @@ -385,17 +384,17 @@ public class OllamaAPI { | ||||
|    * sync/blocking call. | ||||
|    * | ||||
|    * @param model the ollama model to ask the question to | ||||
|    * @param promptText the prompt/question text | ||||
|    * @param prompt the prompt/question text | ||||
|    * @param imageURLs the list of image URLs to use for the question | ||||
|    * @return OllamaResult - that includes response text and time taken for response | ||||
|    * @return OllamaResult that includes response text and time taken for response | ||||
|    */ | ||||
|   public OllamaResult askWithImageURLs(String model, String promptText, List<String> imageURLs) | ||||
|   public OllamaResult askWithImageURLs(String model, String prompt, List<String> imageURLs) | ||||
|       throws OllamaBaseException, IOException, InterruptedException, URISyntaxException { | ||||
|     List<String> images = new ArrayList<>(); | ||||
|     for (String imageURL : imageURLs) { | ||||
|       images.add(encodeByteArrayToBase64(loadImageBytesFromUrl(imageURL))); | ||||
|     } | ||||
|     OllamaRequestModel ollamaRequestModel = new OllamaRequestModel(model, promptText, images); | ||||
|     OllamaRequestModel ollamaRequestModel = new OllamaRequestModel(model, prompt, images); | ||||
|     return askSync(ollamaRequestModel); | ||||
|   } | ||||
|  | ||||
| @@ -426,14 +425,13 @@ public class OllamaAPI { | ||||
|     long startTime = System.currentTimeMillis(); | ||||
|     HttpClient httpClient = HttpClient.newHttpClient(); | ||||
|     URI uri = URI.create(this.host + "/api/generate"); | ||||
|     HttpRequest request = | ||||
|         HttpRequest.newBuilder(uri) | ||||
|     HttpRequest.Builder requestBuilder = | ||||
|         getRequestBuilderDefault(uri) | ||||
|             .POST( | ||||
|                 HttpRequest.BodyPublishers.ofString( | ||||
|                     Utils.getObjectMapper().writeValueAsString(ollamaRequestModel))) | ||||
|             .header("Content-Type", "application/json") | ||||
|             .timeout(Duration.ofSeconds(requestTimeoutSeconds)) | ||||
|             .build(); | ||||
|                     Utils.getObjectMapper().writeValueAsString(ollamaRequestModel))); | ||||
|     HttpRequest request = requestBuilder.build(); | ||||
|     logger.debug("Ask model '" + ollamaRequestModel + "' ..."); | ||||
|     HttpResponse<InputStream> response = | ||||
|         httpClient.send(request, HttpResponse.BodyHandlers.ofInputStream()); | ||||
|     int statusCode = response.statusCode(); | ||||
| @@ -444,9 +442,16 @@ public class OllamaAPI { | ||||
|       String line; | ||||
|       while ((line = reader.readLine()) != null) { | ||||
|         if (statusCode == 404) { | ||||
|           logger.warn("Status code: 404 (Not Found)"); | ||||
|           OllamaErrorResponseModel ollamaResponseModel = | ||||
|               Utils.getObjectMapper().readValue(line, OllamaErrorResponseModel.class); | ||||
|           responseBuffer.append(ollamaResponseModel.getError()); | ||||
|         } else if (statusCode == 401) { | ||||
|           logger.warn("Status code: 401 (Unauthorized)"); | ||||
|           OllamaErrorResponseModel ollamaResponseModel = | ||||
|               Utils.getObjectMapper() | ||||
|                   .readValue("{\"error\":\"Unauthorized\"}", OllamaErrorResponseModel.class); | ||||
|           responseBuffer.append(ollamaResponseModel.getError()); | ||||
|         } else { | ||||
|           OllamaResponseModel ollamaResponseModel = | ||||
|               Utils.getObjectMapper().readValue(line, OllamaResponseModel.class); | ||||
| @@ -457,10 +462,47 @@ public class OllamaAPI { | ||||
|       } | ||||
|     } | ||||
|     if (statusCode != 200) { | ||||
|       logger.error("Status code " + statusCode); | ||||
|       throw new OllamaBaseException(responseBuffer.toString()); | ||||
|     } else { | ||||
|       long endTime = System.currentTimeMillis(); | ||||
|       return new OllamaResult(responseBuffer.toString().trim(), endTime - startTime, statusCode); | ||||
|     } | ||||
|   } | ||||
|  | ||||
|   /** | ||||
|    * Get default request builder. | ||||
|    * | ||||
|    * @param uri URI to get a HttpRequest.Builder | ||||
|    * @return HttpRequest.Builder | ||||
|    */ | ||||
|   private HttpRequest.Builder getRequestBuilderDefault(URI uri) { | ||||
|     HttpRequest.Builder requestBuilder = | ||||
|         HttpRequest.newBuilder(uri) | ||||
|             .header("Content-Type", "application/json") | ||||
|             .timeout(Duration.ofSeconds(requestTimeoutSeconds)); | ||||
|     if (isBasicAuthCredentialsSet()) { | ||||
|       requestBuilder.header("Authorization", getBasicAuthHeaderValue()); | ||||
|     } | ||||
|     return requestBuilder; | ||||
|   } | ||||
|  | ||||
|   /** | ||||
|    * Get basic authentication header value. | ||||
|    * | ||||
|    * @return basic authentication header value (encoded credentials) | ||||
|    */ | ||||
|   private String getBasicAuthHeaderValue() { | ||||
|     String credentialsToEncode = basicAuth.getUsername() + ":" + basicAuth.getPassword(); | ||||
|     return "Basic " + Base64.getEncoder().encodeToString(credentialsToEncode.getBytes()); | ||||
|   } | ||||
|  | ||||
|   /** | ||||
|    * Check if Basic Auth credentials set. | ||||
|    * | ||||
|    * @return true when Basic Auth credentials set | ||||
|    */ | ||||
|   private boolean isBasicAuthCredentialsSet() { | ||||
|     return basicAuth != null; | ||||
|   } | ||||
| } | ||||
|   | ||||
| @@ -0,0 +1,13 @@ | ||||
| package io.github.amithkoujalgi.ollama4j.core.models; | ||||
|  | ||||
| import lombok.AllArgsConstructor; | ||||
| import lombok.Data; | ||||
| import lombok.NoArgsConstructor; | ||||
|  | ||||
| @Data | ||||
| @NoArgsConstructor | ||||
| @AllArgsConstructor | ||||
| public class BasicAuth { | ||||
|   private String username; | ||||
|   private String password; | ||||
| } | ||||
| @@ -6,7 +6,6 @@ import java.io.BufferedReader; | ||||
| import java.io.IOException; | ||||
| import java.io.InputStream; | ||||
| import java.io.InputStreamReader; | ||||
| import java.net.URI; | ||||
| import java.net.http.HttpClient; | ||||
| import java.net.http.HttpRequest; | ||||
| import java.net.http.HttpResponse; | ||||
| @@ -14,30 +13,44 @@ import java.nio.charset.StandardCharsets; | ||||
| import java.time.Duration; | ||||
| import java.util.LinkedList; | ||||
| import java.util.Queue; | ||||
| import lombok.Data; | ||||
| import lombok.EqualsAndHashCode; | ||||
| import lombok.Getter; | ||||
|  | ||||
| @Data | ||||
| @EqualsAndHashCode(callSuper = true) | ||||
| @SuppressWarnings("unused") | ||||
| public class OllamaAsyncResultCallback extends Thread { | ||||
|   private final HttpClient client; | ||||
|   private final URI uri; | ||||
|   private final HttpRequest.Builder requestBuilder; | ||||
|   private final OllamaRequestModel ollamaRequestModel; | ||||
|   private final Queue<String> queue = new LinkedList<>(); | ||||
|   private String result; | ||||
|   private boolean isDone; | ||||
|   private boolean succeeded; | ||||
|  | ||||
|   /** | ||||
|    * -- GETTER -- Returns the status of the request. Indicates if the request was successful or a | ||||
|    * failure. If the request was a failure, the `getResponse()` method will return the error | ||||
|    * message. | ||||
|    */ | ||||
|   @Getter private boolean succeeded; | ||||
|  | ||||
|   private long requestTimeoutSeconds; | ||||
|  | ||||
|   private int httpStatusCode; | ||||
|   private long responseTime = 0; | ||||
|   /** | ||||
|    * -- GETTER -- Returns the HTTP response status code for the request that was made to Ollama | ||||
|    * server. | ||||
|    */ | ||||
|   @Getter private int httpStatusCode; | ||||
|  | ||||
|   /** -- GETTER -- Returns the response time in milliseconds. */ | ||||
|   @Getter private long responseTime = 0; | ||||
|  | ||||
|   public OllamaAsyncResultCallback( | ||||
|       HttpClient client, | ||||
|       URI uri, | ||||
|       HttpRequest.Builder requestBuilder, | ||||
|       OllamaRequestModel ollamaRequestModel, | ||||
|       long requestTimeoutSeconds) { | ||||
|     this.client = client; | ||||
|     this.requestBuilder = requestBuilder; | ||||
|     this.ollamaRequestModel = ollamaRequestModel; | ||||
|     this.uri = uri; | ||||
|     this.isDone = false; | ||||
|     this.result = ""; | ||||
|     this.queue.add(""); | ||||
| @@ -46,10 +59,11 @@ public class OllamaAsyncResultCallback extends Thread { | ||||
|  | ||||
|   @Override | ||||
|   public void run() { | ||||
|     HttpClient httpClient = HttpClient.newHttpClient(); | ||||
|     try { | ||||
|       long startTime = System.currentTimeMillis(); | ||||
|       HttpRequest request = | ||||
|           HttpRequest.newBuilder(uri) | ||||
|           requestBuilder | ||||
|               .POST( | ||||
|                   HttpRequest.BodyPublishers.ofString( | ||||
|                       Utils.getObjectMapper().writeValueAsString(ollamaRequestModel))) | ||||
| @@ -57,7 +71,7 @@ public class OllamaAsyncResultCallback extends Thread { | ||||
|               .timeout(Duration.ofSeconds(requestTimeoutSeconds)) | ||||
|               .build(); | ||||
|       HttpResponse<InputStream> response = | ||||
|           client.send(request, HttpResponse.BodyHandlers.ofInputStream()); | ||||
|           httpClient.send(request, HttpResponse.BodyHandlers.ofInputStream()); | ||||
|       int statusCode = response.statusCode(); | ||||
|       this.httpStatusCode = statusCode; | ||||
|  | ||||
| @@ -108,25 +122,6 @@ public class OllamaAsyncResultCallback extends Thread { | ||||
|     return isDone; | ||||
|   } | ||||
|  | ||||
|   /** | ||||
|    * Returns the HTTP response status code for the request that was made to Ollama server. | ||||
|    * | ||||
|    * @return int - the status code for the request | ||||
|    */ | ||||
|   public int getHttpStatusCode() { | ||||
|     return httpStatusCode; | ||||
|   } | ||||
|  | ||||
|   /** | ||||
|    * Returns the status of the request. Indicates if the request was successful or a failure. If the | ||||
|    * request was a failure, the `getResponse()` method will return the error message. | ||||
|    * | ||||
|    * @return boolean - status | ||||
|    */ | ||||
|   public boolean isSucceeded() { | ||||
|     return succeeded; | ||||
|   } | ||||
|  | ||||
|   /** | ||||
|    * Returns the final response when the execution completes. Does not return intermediate results. | ||||
|    * | ||||
| @@ -140,15 +135,6 @@ public class OllamaAsyncResultCallback extends Thread { | ||||
|     return queue; | ||||
|   } | ||||
|  | ||||
|   /** | ||||
|    * Returns the response time in milliseconds. | ||||
|    * | ||||
|    * @return long - response time in milliseconds. | ||||
|    */ | ||||
|   public long getResponseTime() { | ||||
|     return responseTime; | ||||
|   } | ||||
|  | ||||
|   public void setRequestTimeoutSeconds(long requestTimeoutSeconds) { | ||||
|     this.requestTimeoutSeconds = requestTimeoutSeconds; | ||||
|   } | ||||
|   | ||||
| @@ -11,12 +11,13 @@ import io.github.amithkoujalgi.ollama4j.core.types.OllamaModelType; | ||||
| import java.io.IOException; | ||||
| import java.net.URISyntaxException; | ||||
| import java.util.ArrayList; | ||||
| import java.util.Collections; | ||||
| import org.junit.jupiter.api.Test; | ||||
| import org.mockito.Mockito; | ||||
|  | ||||
| class TestMockedAPIs { | ||||
|   @Test | ||||
|   void testMockPullModel() { | ||||
|   void testPullModel() { | ||||
|     OllamaAPI ollamaAPI = Mockito.mock(OllamaAPI.class); | ||||
|     String model = OllamaModelType.LLAMA2; | ||||
|     try { | ||||
| @@ -49,7 +50,7 @@ class TestMockedAPIs { | ||||
|       doNothing().when(ollamaAPI).createModelWithModelFileContents(model, modelFilePath); | ||||
|       ollamaAPI.createModelWithModelFileContents(model, modelFilePath); | ||||
|       verify(ollamaAPI, times(1)).createModelWithModelFileContents(model, modelFilePath); | ||||
|     } catch (IOException | OllamaBaseException | InterruptedException e) { | ||||
|     } catch (IOException | OllamaBaseException | InterruptedException | URISyntaxException e) { | ||||
|       throw new RuntimeException(e); | ||||
|     } | ||||
|   } | ||||
| @@ -62,7 +63,7 @@ class TestMockedAPIs { | ||||
|       doNothing().when(ollamaAPI).deleteModel(model, true); | ||||
|       ollamaAPI.deleteModel(model, true); | ||||
|       verify(ollamaAPI, times(1)).deleteModel(model, true); | ||||
|     } catch (IOException | OllamaBaseException | InterruptedException e) { | ||||
|     } catch (IOException | OllamaBaseException | InterruptedException | URISyntaxException e) { | ||||
|       throw new RuntimeException(e); | ||||
|     } | ||||
|   } | ||||
| @@ -75,7 +76,7 @@ class TestMockedAPIs { | ||||
|       when(ollamaAPI.getModelDetails(model)).thenReturn(new ModelDetail()); | ||||
|       ollamaAPI.getModelDetails(model); | ||||
|       verify(ollamaAPI, times(1)).getModelDetails(model); | ||||
|     } catch (IOException | OllamaBaseException | InterruptedException e) { | ||||
|     } catch (IOException | OllamaBaseException | InterruptedException | URISyntaxException e) { | ||||
|       throw new RuntimeException(e); | ||||
|     } | ||||
|   } | ||||
| @@ -108,13 +109,43 @@ class TestMockedAPIs { | ||||
|     } | ||||
|   } | ||||
|  | ||||
|   @Test | ||||
|   void testAskWithImageFiles() { | ||||
|     OllamaAPI ollamaAPI = Mockito.mock(OllamaAPI.class); | ||||
|     String model = OllamaModelType.LLAMA2; | ||||
|     String prompt = "some prompt text"; | ||||
|     try { | ||||
|       when(ollamaAPI.askWithImageFiles(model, prompt, Collections.emptyList())) | ||||
|           .thenReturn(new OllamaResult("", 0, 200)); | ||||
|       ollamaAPI.askWithImageFiles(model, prompt, Collections.emptyList()); | ||||
|       verify(ollamaAPI, times(1)).askWithImageFiles(model, prompt, Collections.emptyList()); | ||||
|     } catch (IOException | OllamaBaseException | InterruptedException e) { | ||||
|       throw new RuntimeException(e); | ||||
|     } | ||||
|   } | ||||
|  | ||||
|   @Test | ||||
|   void testAskWithImageURLs() { | ||||
|     OllamaAPI ollamaAPI = Mockito.mock(OllamaAPI.class); | ||||
|     String model = OllamaModelType.LLAMA2; | ||||
|     String prompt = "some prompt text"; | ||||
|     try { | ||||
|       when(ollamaAPI.askWithImageURLs(model, prompt, Collections.emptyList())) | ||||
|           .thenReturn(new OllamaResult("", 0, 200)); | ||||
|       ollamaAPI.askWithImageURLs(model, prompt, Collections.emptyList()); | ||||
|       verify(ollamaAPI, times(1)).askWithImageURLs(model, prompt, Collections.emptyList()); | ||||
|     } catch (IOException | OllamaBaseException | InterruptedException | URISyntaxException e) { | ||||
|       throw new RuntimeException(e); | ||||
|     } | ||||
|   } | ||||
|  | ||||
|   @Test | ||||
|   void testAskAsync() { | ||||
|     OllamaAPI ollamaAPI = Mockito.mock(OllamaAPI.class); | ||||
|     String model = OllamaModelType.LLAMA2; | ||||
|     String prompt = "some prompt text"; | ||||
|     when(ollamaAPI.askAsync(model, prompt)) | ||||
|         .thenReturn(new OllamaAsyncResultCallback(null, null, null, 3)); | ||||
|         .thenReturn(new OllamaAsyncResultCallback(null, null, 3)); | ||||
|     ollamaAPI.askAsync(model, prompt); | ||||
|     verify(ollamaAPI, times(1)).askAsync(model, prompt); | ||||
|   } | ||||
|   | ||||
		Reference in New Issue
	
	Block a user