Refactor OllamaAPI to use Constants for HTTP headers and improve logging format

- Introduced a new Constants class to centralize HTTP header values.
- Updated OllamaAPI methods to utilize Constants for "Content-Type" and "Accept" headers.
- Enhanced logging statements to use parameterized messages for better performance and readability.
- Added a test for the ping method in OllamaAPIIntegrationTest to ensure connectivity.
This commit is contained in:
amithkoujalgi 2025-08-30 13:01:01 +05:30
parent f085b633af
commit cc950b893e
No known key found for this signature in database
GPG Key ID: E29A37746AF94B70
11 changed files with 134 additions and 60 deletions

View File

@ -22,6 +22,7 @@ import io.github.ollama4j.tools.*;
import io.github.ollama4j.tools.annotations.OllamaToolService; import io.github.ollama4j.tools.annotations.OllamaToolService;
import io.github.ollama4j.tools.annotations.ToolProperty; import io.github.ollama4j.tools.annotations.ToolProperty;
import io.github.ollama4j.tools.annotations.ToolSpec; import io.github.ollama4j.tools.annotations.ToolSpec;
import io.github.ollama4j.utils.Constants;
import io.github.ollama4j.utils.Options; import io.github.ollama4j.utils.Options;
import io.github.ollama4j.utils.Utils; import io.github.ollama4j.utils.Utils;
import lombok.Setter; import lombok.Setter;
@ -102,7 +103,7 @@ public class OllamaAPI {
this.host = host; this.host = host;
} }
if (this.verbose) { if (this.verbose) {
logger.info("Ollama API initialized with host: " + this.host); logger.info("Ollama API initialized with host: {}", this.host);
} }
} }
@ -135,13 +136,17 @@ public class OllamaAPI {
public boolean ping() { public boolean ping() {
String url = this.host + "/api/tags"; String url = this.host + "/api/tags";
HttpClient httpClient = HttpClient.newHttpClient(); HttpClient httpClient = HttpClient.newHttpClient();
HttpRequest httpRequest = null; HttpRequest httpRequest;
try { try {
httpRequest = getRequestBuilderDefault(new URI(url)).header("Accept", "application/json").header("Content-type", "application/json").GET().build(); httpRequest = getRequestBuilderDefault(new URI(url))
.header(Constants.HttpConstants.HEADER_KEY_ACCEPT, Constants.HttpConstants.APPLICATION_JSON)
.header(Constants.HttpConstants.HEADER_KEY_CONTENT_TYPE, Constants.HttpConstants.APPLICATION_JSON)
.GET()
.build();
} catch (URISyntaxException e) { } catch (URISyntaxException e) {
throw new RuntimeException(e); throw new RuntimeException(e);
} }
HttpResponse<String> response = null; HttpResponse<String> response;
try { try {
response = httpClient.send(httpRequest, HttpResponse.BodyHandlers.ofString()); response = httpClient.send(httpRequest, HttpResponse.BodyHandlers.ofString());
} catch (HttpConnectTimeoutException e) { } catch (HttpConnectTimeoutException e) {
@ -167,7 +172,7 @@ public class OllamaAPI {
HttpClient httpClient = HttpClient.newHttpClient(); HttpClient httpClient = HttpClient.newHttpClient();
HttpRequest httpRequest = null; HttpRequest httpRequest = null;
try { try {
httpRequest = getRequestBuilderDefault(new URI(url)).header("Accept", "application/json").header("Content-type", "application/json").GET().build(); httpRequest = getRequestBuilderDefault(new URI(url)).header(Constants.HttpConstants.HEADER_KEY_ACCEPT, Constants.HttpConstants.APPLICATION_JSON).header(Constants.HttpConstants.HEADER_KEY_CONTENT_TYPE, Constants.HttpConstants.APPLICATION_JSON).GET().build();
} catch (URISyntaxException e) { } catch (URISyntaxException e) {
throw new RuntimeException(e); throw new RuntimeException(e);
} }
@ -194,7 +199,7 @@ public class OllamaAPI {
public List<Model> listModels() throws OllamaBaseException, IOException, InterruptedException, URISyntaxException { public List<Model> listModels() throws OllamaBaseException, IOException, InterruptedException, URISyntaxException {
String url = this.host + "/api/tags"; String url = this.host + "/api/tags";
HttpClient httpClient = HttpClient.newHttpClient(); HttpClient httpClient = HttpClient.newHttpClient();
HttpRequest httpRequest = getRequestBuilderDefault(new URI(url)).header("Accept", "application/json").header("Content-type", "application/json").GET().build(); HttpRequest httpRequest = getRequestBuilderDefault(new URI(url)).header(Constants.HttpConstants.HEADER_KEY_ACCEPT, Constants.HttpConstants.APPLICATION_JSON).header(Constants.HttpConstants.HEADER_KEY_CONTENT_TYPE, Constants.HttpConstants.APPLICATION_JSON).GET().build();
HttpResponse<String> response = httpClient.send(httpRequest, HttpResponse.BodyHandlers.ofString()); HttpResponse<String> response = httpClient.send(httpRequest, HttpResponse.BodyHandlers.ofString());
int statusCode = response.statusCode(); int statusCode = response.statusCode();
String responseString = response.body(); String responseString = response.body();
@ -225,7 +230,7 @@ public class OllamaAPI {
public List<LibraryModel> listModelsFromLibrary() throws OllamaBaseException, IOException, InterruptedException, URISyntaxException { public List<LibraryModel> listModelsFromLibrary() throws OllamaBaseException, IOException, InterruptedException, URISyntaxException {
String url = "https://ollama.com/library"; String url = "https://ollama.com/library";
HttpClient httpClient = HttpClient.newHttpClient(); HttpClient httpClient = HttpClient.newHttpClient();
HttpRequest httpRequest = getRequestBuilderDefault(new URI(url)).header("Accept", "application/json").header("Content-type", "application/json").GET().build(); HttpRequest httpRequest = getRequestBuilderDefault(new URI(url)).header(Constants.HttpConstants.HEADER_KEY_ACCEPT, Constants.HttpConstants.APPLICATION_JSON).header(Constants.HttpConstants.HEADER_KEY_CONTENT_TYPE, Constants.HttpConstants.APPLICATION_JSON).GET().build();
HttpResponse<String> response = httpClient.send(httpRequest, HttpResponse.BodyHandlers.ofString()); HttpResponse<String> response = httpClient.send(httpRequest, HttpResponse.BodyHandlers.ofString());
int statusCode = response.statusCode(); int statusCode = response.statusCode();
String responseString = response.body(); String responseString = response.body();
@ -286,7 +291,7 @@ public class OllamaAPI {
public LibraryModelDetail getLibraryModelDetails(LibraryModel libraryModel) throws OllamaBaseException, IOException, InterruptedException, URISyntaxException { public LibraryModelDetail getLibraryModelDetails(LibraryModel libraryModel) throws OllamaBaseException, IOException, InterruptedException, URISyntaxException {
String url = String.format("https://ollama.com/library/%s/tags", libraryModel.getName()); String url = String.format("https://ollama.com/library/%s/tags", libraryModel.getName());
HttpClient httpClient = HttpClient.newHttpClient(); HttpClient httpClient = HttpClient.newHttpClient();
HttpRequest httpRequest = getRequestBuilderDefault(new URI(url)).header("Accept", "application/json").header("Content-type", "application/json").GET().build(); HttpRequest httpRequest = getRequestBuilderDefault(new URI(url)).header(Constants.HttpConstants.HEADER_KEY_ACCEPT, Constants.HttpConstants.APPLICATION_JSON).header(Constants.HttpConstants.HEADER_KEY_CONTENT_TYPE, Constants.HttpConstants.APPLICATION_JSON).GET().build();
HttpResponse<String> response = httpClient.send(httpRequest, HttpResponse.BodyHandlers.ofString()); HttpResponse<String> response = httpClient.send(httpRequest, HttpResponse.BodyHandlers.ofString());
int statusCode = response.statusCode(); int statusCode = response.statusCode();
String responseString = response.body(); String responseString = response.body();
@ -380,7 +385,7 @@ public class OllamaAPI {
private void doPullModel(String modelName) throws OllamaBaseException, IOException, URISyntaxException, InterruptedException { private void doPullModel(String modelName) throws OllamaBaseException, IOException, URISyntaxException, InterruptedException {
String url = this.host + "/api/pull"; String url = this.host + "/api/pull";
String jsonData = new ModelRequest(modelName).toString(); String jsonData = new ModelRequest(modelName).toString();
HttpRequest request = getRequestBuilderDefault(new URI(url)).POST(HttpRequest.BodyPublishers.ofString(jsonData)).header("Accept", "application/json").header("Content-type", "application/json").build(); HttpRequest request = getRequestBuilderDefault(new URI(url)).POST(HttpRequest.BodyPublishers.ofString(jsonData)).header(Constants.HttpConstants.HEADER_KEY_ACCEPT, Constants.HttpConstants.APPLICATION_JSON).header(Constants.HttpConstants.HEADER_KEY_CONTENT_TYPE, Constants.HttpConstants.APPLICATION_JSON).build();
HttpClient client = HttpClient.newHttpClient(); HttpClient client = HttpClient.newHttpClient();
HttpResponse<InputStream> response = client.send(request, HttpResponse.BodyHandlers.ofInputStream()); HttpResponse<InputStream> response = client.send(request, HttpResponse.BodyHandlers.ofInputStream());
int statusCode = response.statusCode(); int statusCode = response.statusCode();
@ -399,7 +404,7 @@ public class OllamaAPI {
if (modelPullResponse.getStatus() != null) { if (modelPullResponse.getStatus() != null) {
if (verbose) { if (verbose) {
logger.info(modelName + ": " + modelPullResponse.getStatus()); logger.info("{}: {}", modelName, modelPullResponse.getStatus());
} }
// Check if status is "success" and set success flag to true. // Check if status is "success" and set success flag to true.
if ("success".equalsIgnoreCase(modelPullResponse.getStatus())) { if ("success".equalsIgnoreCase(modelPullResponse.getStatus())) {
@ -423,7 +428,7 @@ public class OllamaAPI {
public String getVersion() throws URISyntaxException, IOException, InterruptedException, OllamaBaseException { public String getVersion() throws URISyntaxException, IOException, InterruptedException, OllamaBaseException {
String url = this.host + "/api/version"; String url = this.host + "/api/version";
HttpClient httpClient = HttpClient.newHttpClient(); HttpClient httpClient = HttpClient.newHttpClient();
HttpRequest httpRequest = getRequestBuilderDefault(new URI(url)).header("Accept", "application/json").header("Content-type", "application/json").GET().build(); HttpRequest httpRequest = getRequestBuilderDefault(new URI(url)).header(Constants.HttpConstants.HEADER_KEY_ACCEPT, Constants.HttpConstants.APPLICATION_JSON).header(Constants.HttpConstants.HEADER_KEY_CONTENT_TYPE, Constants.HttpConstants.APPLICATION_JSON).GET().build();
HttpResponse<String> response = httpClient.send(httpRequest, HttpResponse.BodyHandlers.ofString()); HttpResponse<String> response = httpClient.send(httpRequest, HttpResponse.BodyHandlers.ofString());
int statusCode = response.statusCode(); int statusCode = response.statusCode();
String responseString = response.body(); String responseString = response.body();
@ -466,7 +471,7 @@ public class OllamaAPI {
public ModelDetail getModelDetails(String modelName) throws IOException, OllamaBaseException, InterruptedException, URISyntaxException { public ModelDetail getModelDetails(String modelName) throws IOException, OllamaBaseException, InterruptedException, URISyntaxException {
String url = this.host + "/api/show"; String url = this.host + "/api/show";
String jsonData = new ModelRequest(modelName).toString(); String jsonData = new ModelRequest(modelName).toString();
HttpRequest request = getRequestBuilderDefault(new URI(url)).header("Accept", "application/json").header("Content-type", "application/json").POST(HttpRequest.BodyPublishers.ofString(jsonData)).build(); HttpRequest request = getRequestBuilderDefault(new URI(url)).header(Constants.HttpConstants.HEADER_KEY_ACCEPT, Constants.HttpConstants.APPLICATION_JSON).header(Constants.HttpConstants.HEADER_KEY_CONTENT_TYPE, Constants.HttpConstants.APPLICATION_JSON).POST(HttpRequest.BodyPublishers.ofString(jsonData)).build();
HttpClient client = HttpClient.newHttpClient(); HttpClient client = HttpClient.newHttpClient();
HttpResponse<String> response = client.send(request, HttpResponse.BodyHandlers.ofString()); HttpResponse<String> response = client.send(request, HttpResponse.BodyHandlers.ofString());
int statusCode = response.statusCode(); int statusCode = response.statusCode();
@ -495,7 +500,7 @@ public class OllamaAPI {
public void createModelWithFilePath(String modelName, String modelFilePath) throws IOException, InterruptedException, OllamaBaseException, URISyntaxException { public void createModelWithFilePath(String modelName, String modelFilePath) throws IOException, InterruptedException, OllamaBaseException, URISyntaxException {
String url = this.host + "/api/create"; String url = this.host + "/api/create";
String jsonData = new CustomModelFilePathRequest(modelName, modelFilePath).toString(); String jsonData = new CustomModelFilePathRequest(modelName, modelFilePath).toString();
HttpRequest request = getRequestBuilderDefault(new URI(url)).header("Accept", "application/json").header("Content-Type", "application/json").POST(HttpRequest.BodyPublishers.ofString(jsonData, StandardCharsets.UTF_8)).build(); HttpRequest request = getRequestBuilderDefault(new URI(url)).header(Constants.HttpConstants.HEADER_KEY_ACCEPT, Constants.HttpConstants.APPLICATION_JSON).header(Constants.HttpConstants.HEADER_KEY_CONTENT_TYPE, Constants.HttpConstants.APPLICATION_JSON).POST(HttpRequest.BodyPublishers.ofString(jsonData, StandardCharsets.UTF_8)).build();
HttpClient client = HttpClient.newHttpClient(); HttpClient client = HttpClient.newHttpClient();
HttpResponse<String> response = client.send(request, HttpResponse.BodyHandlers.ofString()); HttpResponse<String> response = client.send(request, HttpResponse.BodyHandlers.ofString());
int statusCode = response.statusCode(); int statusCode = response.statusCode();
@ -532,7 +537,7 @@ public class OllamaAPI {
public void createModelWithModelFileContents(String modelName, String modelFileContents) throws IOException, InterruptedException, OllamaBaseException, URISyntaxException { public void createModelWithModelFileContents(String modelName, String modelFileContents) throws IOException, InterruptedException, OllamaBaseException, URISyntaxException {
String url = this.host + "/api/create"; String url = this.host + "/api/create";
String jsonData = new CustomModelFileContentsRequest(modelName, modelFileContents).toString(); String jsonData = new CustomModelFileContentsRequest(modelName, modelFileContents).toString();
HttpRequest request = getRequestBuilderDefault(new URI(url)).header("Accept", "application/json").header("Content-Type", "application/json").POST(HttpRequest.BodyPublishers.ofString(jsonData, StandardCharsets.UTF_8)).build(); HttpRequest request = getRequestBuilderDefault(new URI(url)).header(Constants.HttpConstants.HEADER_KEY_ACCEPT, Constants.HttpConstants.APPLICATION_JSON).header(Constants.HttpConstants.HEADER_KEY_CONTENT_TYPE, Constants.HttpConstants.APPLICATION_JSON).POST(HttpRequest.BodyPublishers.ofString(jsonData, StandardCharsets.UTF_8)).build();
HttpClient client = HttpClient.newHttpClient(); HttpClient client = HttpClient.newHttpClient();
HttpResponse<String> response = client.send(request, HttpResponse.BodyHandlers.ofString()); HttpResponse<String> response = client.send(request, HttpResponse.BodyHandlers.ofString());
int statusCode = response.statusCode(); int statusCode = response.statusCode();
@ -562,7 +567,7 @@ public class OllamaAPI {
public void createModel(CustomModelRequest customModelRequest) throws IOException, InterruptedException, OllamaBaseException, URISyntaxException { public void createModel(CustomModelRequest customModelRequest) throws IOException, InterruptedException, OllamaBaseException, URISyntaxException {
String url = this.host + "/api/create"; String url = this.host + "/api/create";
String jsonData = customModelRequest.toString(); String jsonData = customModelRequest.toString();
HttpRequest request = getRequestBuilderDefault(new URI(url)).header("Accept", "application/json").header("Content-Type", "application/json").POST(HttpRequest.BodyPublishers.ofString(jsonData, StandardCharsets.UTF_8)).build(); HttpRequest request = getRequestBuilderDefault(new URI(url)).header(Constants.HttpConstants.HEADER_KEY_ACCEPT, Constants.HttpConstants.APPLICATION_JSON).header(Constants.HttpConstants.HEADER_KEY_CONTENT_TYPE, Constants.HttpConstants.APPLICATION_JSON).POST(HttpRequest.BodyPublishers.ofString(jsonData, StandardCharsets.UTF_8)).build();
HttpClient client = HttpClient.newHttpClient(); HttpClient client = HttpClient.newHttpClient();
HttpResponse<String> response = client.send(request, HttpResponse.BodyHandlers.ofString()); HttpResponse<String> response = client.send(request, HttpResponse.BodyHandlers.ofString());
int statusCode = response.statusCode(); int statusCode = response.statusCode();
@ -592,7 +597,7 @@ public class OllamaAPI {
public void deleteModel(String modelName, boolean ignoreIfNotPresent) throws IOException, InterruptedException, OllamaBaseException, URISyntaxException { public void deleteModel(String modelName, boolean ignoreIfNotPresent) throws IOException, InterruptedException, OllamaBaseException, URISyntaxException {
String url = this.host + "/api/delete"; String url = this.host + "/api/delete";
String jsonData = new ModelRequest(modelName).toString(); String jsonData = new ModelRequest(modelName).toString();
HttpRequest request = getRequestBuilderDefault(new URI(url)).method("DELETE", HttpRequest.BodyPublishers.ofString(jsonData, StandardCharsets.UTF_8)).header("Accept", "application/json").header("Content-type", "application/json").build(); HttpRequest request = getRequestBuilderDefault(new URI(url)).method("DELETE", HttpRequest.BodyPublishers.ofString(jsonData, StandardCharsets.UTF_8)).header(Constants.HttpConstants.HEADER_KEY_ACCEPT, Constants.HttpConstants.APPLICATION_JSON).header(Constants.HttpConstants.HEADER_KEY_CONTENT_TYPE, Constants.HttpConstants.APPLICATION_JSON).build();
HttpClient client = HttpClient.newHttpClient(); HttpClient client = HttpClient.newHttpClient();
HttpResponse<String> response = client.send(request, HttpResponse.BodyHandlers.ofString()); HttpResponse<String> response = client.send(request, HttpResponse.BodyHandlers.ofString());
int statusCode = response.statusCode(); int statusCode = response.statusCode();
@ -636,7 +641,7 @@ public class OllamaAPI {
URI uri = URI.create(this.host + "/api/embeddings"); URI uri = URI.create(this.host + "/api/embeddings");
String jsonData = modelRequest.toString(); String jsonData = modelRequest.toString();
HttpClient httpClient = HttpClient.newHttpClient(); HttpClient httpClient = HttpClient.newHttpClient();
HttpRequest.Builder requestBuilder = getRequestBuilderDefault(uri).header("Accept", "application/json").POST(HttpRequest.BodyPublishers.ofString(jsonData)); HttpRequest.Builder requestBuilder = getRequestBuilderDefault(uri).header(Constants.HttpConstants.HEADER_KEY_ACCEPT, Constants.HttpConstants.APPLICATION_JSON).POST(HttpRequest.BodyPublishers.ofString(jsonData));
HttpRequest request = requestBuilder.build(); HttpRequest request = requestBuilder.build();
HttpResponse<String> response = httpClient.send(request, HttpResponse.BodyHandlers.ofString()); HttpResponse<String> response = httpClient.send(request, HttpResponse.BodyHandlers.ofString());
int statusCode = response.statusCode(); int statusCode = response.statusCode();
@ -677,7 +682,7 @@ public class OllamaAPI {
String jsonData = Utils.getObjectMapper().writeValueAsString(modelRequest); String jsonData = Utils.getObjectMapper().writeValueAsString(modelRequest);
HttpClient httpClient = HttpClient.newHttpClient(); HttpClient httpClient = HttpClient.newHttpClient();
HttpRequest request = HttpRequest.newBuilder(uri).header("Accept", "application/json").POST(HttpRequest.BodyPublishers.ofString(jsonData)).build(); HttpRequest request = HttpRequest.newBuilder(uri).header(Constants.HttpConstants.HEADER_KEY_ACCEPT, Constants.HttpConstants.APPLICATION_JSON).POST(HttpRequest.BodyPublishers.ofString(jsonData)).build();
HttpResponse<String> response = httpClient.send(request, HttpResponse.BodyHandlers.ofString()); HttpResponse<String> response = httpClient.send(request, HttpResponse.BodyHandlers.ofString());
int statusCode = response.statusCode(); int statusCode = response.statusCode();
@ -774,7 +779,7 @@ public class OllamaAPI {
String jsonData = Utils.getObjectMapper().writeValueAsString(requestBody); String jsonData = Utils.getObjectMapper().writeValueAsString(requestBody);
HttpClient httpClient = HttpClient.newHttpClient(); HttpClient httpClient = HttpClient.newHttpClient();
HttpRequest request = getRequestBuilderDefault(uri).header("Accept", "application/json").header("Content-type", "application/json").POST(HttpRequest.BodyPublishers.ofString(jsonData)).build(); HttpRequest request = getRequestBuilderDefault(uri).header(Constants.HttpConstants.HEADER_KEY_ACCEPT, Constants.HttpConstants.APPLICATION_JSON).header(Constants.HttpConstants.HEADER_KEY_CONTENT_TYPE, Constants.HttpConstants.APPLICATION_JSON).POST(HttpRequest.BodyPublishers.ofString(jsonData)).build();
if (verbose) { if (verbose) {
try { try {
@ -1370,7 +1375,7 @@ public class OllamaAPI {
* @return HttpRequest.Builder * @return HttpRequest.Builder
*/ */
private HttpRequest.Builder getRequestBuilderDefault(URI uri) { private HttpRequest.Builder getRequestBuilderDefault(URI uri) {
HttpRequest.Builder requestBuilder = HttpRequest.newBuilder(uri).header("Content-Type", "application/json").timeout(Duration.ofSeconds(requestTimeoutSeconds)); HttpRequest.Builder requestBuilder = HttpRequest.newBuilder(uri).header(Constants.HttpConstants.HEADER_KEY_CONTENT_TYPE, Constants.HttpConstants.APPLICATION_JSON).timeout(Duration.ofSeconds(requestTimeoutSeconds));
if (isBasicAuthCredentialsSet()) { if (isBasicAuthCredentialsSet()) {
requestBuilder.header("Authorization", auth.getAuthHeaderValue()); requestBuilder.header("Authorization", auth.getAuthHeaderValue());
} }

View File

@ -4,10 +4,11 @@ import java.util.Base64;
import lombok.AllArgsConstructor; import lombok.AllArgsConstructor;
import lombok.Data; import lombok.Data;
import lombok.NoArgsConstructor; import lombok.EqualsAndHashCode;
@Data @Data
@AllArgsConstructor @AllArgsConstructor
@EqualsAndHashCode(callSuper = false)
public class BasicAuth extends Auth { public class BasicAuth extends Auth {
private String username; private String username;
private String password; private String password;

View File

@ -24,6 +24,7 @@ import java.util.List;
/** /**
* Specialization class for requests * Specialization class for requests
*/ */
@SuppressWarnings("resource")
public class OllamaChatEndpointCaller extends OllamaEndpointCaller { public class OllamaChatEndpointCaller extends OllamaEndpointCaller {
private static final Logger LOG = LoggerFactory.getLogger(OllamaChatEndpointCaller.class); private static final Logger LOG = LoggerFactory.getLogger(OllamaChatEndpointCaller.class);

View File

@ -4,6 +4,7 @@ import java.net.URI;
import java.net.http.HttpRequest; import java.net.http.HttpRequest;
import java.time.Duration; import java.time.Duration;
import io.github.ollama4j.utils.Constants;
import org.slf4j.Logger; import org.slf4j.Logger;
import org.slf4j.LoggerFactory; import org.slf4j.LoggerFactory;
@ -44,7 +45,7 @@ public abstract class OllamaEndpointCaller {
protected HttpRequest.Builder getRequestBuilderDefault(URI uri) { protected HttpRequest.Builder getRequestBuilderDefault(URI uri) {
HttpRequest.Builder requestBuilder = HttpRequest.Builder requestBuilder =
HttpRequest.newBuilder(uri) HttpRequest.newBuilder(uri)
.header("Content-Type", "application/json") .header(Constants.HttpConstants.HEADER_KEY_CONTENT_TYPE, Constants.HttpConstants.APPLICATION_JSON)
.timeout(Duration.ofSeconds(this.requestTimeoutSeconds)); .timeout(Duration.ofSeconds(this.requestTimeoutSeconds));
if (isAuthCredentialsSet()) { if (isAuthCredentialsSet()) {
requestBuilder.header("Authorization", this.auth.getAuthHeaderValue()); requestBuilder.header("Authorization", this.auth.getAuthHeaderValue());

View File

@ -22,6 +22,7 @@ import java.net.http.HttpRequest;
import java.net.http.HttpResponse; import java.net.http.HttpResponse;
import java.nio.charset.StandardCharsets; import java.nio.charset.StandardCharsets;
@SuppressWarnings("resource")
public class OllamaGenerateEndpointCaller extends OllamaEndpointCaller { public class OllamaGenerateEndpointCaller extends OllamaEndpointCaller {
private static final Logger LOG = LoggerFactory.getLogger(OllamaGenerateEndpointCaller.class); private static final Logger LOG = LoggerFactory.getLogger(OllamaGenerateEndpointCaller.class);

View File

@ -8,6 +8,7 @@ import lombok.Data;
import lombok.EqualsAndHashCode; import lombok.EqualsAndHashCode;
import lombok.Getter; import lombok.Getter;
import lombok.Setter; import lombok.Setter;
import io.github.ollama4j.utils.Constants;
import java.io.BufferedReader; import java.io.BufferedReader;
import java.io.IOException; import java.io.IOException;
@ -68,14 +69,14 @@ public class OllamaAsyncResultStreamer extends Thread {
public void run() { public void run() {
ollamaRequestModel.setStream(true); ollamaRequestModel.setStream(true);
HttpClient httpClient = HttpClient.newHttpClient(); HttpClient httpClient = HttpClient.newHttpClient();
try {
long startTime = System.currentTimeMillis(); long startTime = System.currentTimeMillis();
try {
HttpRequest request = HttpRequest request =
requestBuilder requestBuilder
.POST( .POST(
HttpRequest.BodyPublishers.ofString( HttpRequest.BodyPublishers.ofString(
Utils.getObjectMapper().writeValueAsString(ollamaRequestModel))) Utils.getObjectMapper().writeValueAsString(ollamaRequestModel)))
.header("Content-Type", "application/json") .header(Constants.HttpConstants.HEADER_KEY_CONTENT_TYPE, Constants.HttpConstants.APPLICATION_JSON)
.timeout(Duration.ofSeconds(requestTimeoutSeconds)) .timeout(Duration.ofSeconds(requestTimeoutSeconds))
.build(); .build();
HttpResponse<InputStream> response = HttpResponse<InputStream> response =
@ -84,8 +85,9 @@ public class OllamaAsyncResultStreamer extends Thread {
this.httpStatusCode = statusCode; this.httpStatusCode = statusCode;
InputStream responseBodyStream = response.body(); InputStream responseBodyStream = response.body();
try (BufferedReader reader = BufferedReader reader = null;
new BufferedReader(new InputStreamReader(responseBodyStream, StandardCharsets.UTF_8))) { try {
reader = new BufferedReader(new InputStreamReader(responseBodyStream, StandardCharsets.UTF_8));
String line; String line;
StringBuilder responseBuffer = new StringBuilder(); StringBuilder responseBuffer = new StringBuilder();
while ((line = reader.readLine()) != null) { while ((line = reader.readLine()) != null) {
@ -109,6 +111,21 @@ public class OllamaAsyncResultStreamer extends Thread {
this.completeResponse = responseBuffer.toString(); this.completeResponse = responseBuffer.toString();
long endTime = System.currentTimeMillis(); long endTime = System.currentTimeMillis();
responseTime = endTime - startTime; responseTime = endTime - startTime;
} finally {
if (reader != null) {
try {
reader.close();
} catch (IOException e) {
// Optionally log or handle
}
}
if (responseBodyStream != null) {
try {
responseBodyStream.close();
} catch (IOException e) {
// Optionally log or handle
}
}
} }
if (statusCode != 200) { if (statusCode != 200) {
throw new OllamaBaseException(this.completeResponse); throw new OllamaBaseException(this.completeResponse);

View File

@ -12,15 +12,17 @@ import com.fasterxml.jackson.databind.ObjectMapper;
import io.github.ollama4j.tools.Tools; import io.github.ollama4j.tools.Tools;
@SuppressWarnings("resource")
public class WeatherTool { public class WeatherTool {
private String openWeatherMapAPIKey = null; private String openWeatherMapAPIKey = null;
private String paramCityName = "cityName";
public WeatherTool(String openWeatherMapAPIKey) { public WeatherTool(String openWeatherMapAPIKey) {
this.openWeatherMapAPIKey = openWeatherMapAPIKey; this.openWeatherMapAPIKey = openWeatherMapAPIKey;
} }
public String getCurrentWeather(Map<String, Object> arguments) { public String getCurrentWeather(Map<String, Object> arguments) {
String city = (String) arguments.get("cityName");
String city = (String) arguments.get(paramCityName);
System.out.println("Finding weather for city: " + city); System.out.println("Finding weather for city: " + city);
String url = String.format("https://api.openweathermap.org/data/2.5/weather?q=%s&appid=%s&units=metric", String url = String.format("https://api.openweathermap.org/data/2.5/weather?q=%s&appid=%s&units=metric",
@ -45,7 +47,6 @@ public class WeatherTool {
+ response.statusCode(); + response.statusCode();
} }
} catch (IOException | InterruptedException e) { } catch (IOException | InterruptedException e) {
e.printStackTrace();
return "Error retrieving weather data: " + e.getMessage(); return "Error retrieving weather data: " + e.getMessage();
} }
} }
@ -70,7 +71,7 @@ public class WeatherTool {
.type("object") .type("object")
.properties( .properties(
Map.of( Map.of(
"cityName", paramCityName,
Tools.PromptFuncDefinition.Property Tools.PromptFuncDefinition.Property
.builder() .builder()
.type("string") .type("string")
@ -79,7 +80,7 @@ public class WeatherTool {
.required(true) .required(true)
.build())) .build()))
.required(java.util.List .required(java.util.List
.of("cityName")) .of(paramCityName))
.build()) .build())
.build()) .build())
.build()) .build())

View File

@ -0,0 +1,14 @@
package io.github.ollama4j.utils;
public final class Constants {
public static final class HttpConstants {
private HttpConstants() {
}
public static final String APPLICATION_JSON = "application/json";
public static final String APPLICATION_XML = "application/xml";
public static final String TEXT_PLAIN = "text/plain";
public static final String HEADER_KEY_CONTENT_TYPE = "Content-Type";
public static final String HEADER_KEY_ACCEPT = "Accept";
}
}

View File

@ -16,7 +16,7 @@ public class SamplePrompts {
stringBuffer.append(scanner.nextLine()).append("\n"); stringBuffer.append(scanner.nextLine()).append("\n");
} }
scanner.close(); scanner.close();
return stringBuffer.toString().replaceAll("<question>", question); return stringBuffer.toString().replace("<question>", question);
} else { } else {
throw new Exception("Sample database question file not found."); throw new Exception("Sample database question file not found.");
} }

View File

@ -98,6 +98,13 @@ public class OllamaAPIIntegrationTest {
// image version"); // image version");
} }
@Test
@Order(1)
public void testPing() throws URISyntaxException, IOException, OllamaBaseException, InterruptedException {
boolean pingResponse = api.ping();
assertTrue(pingResponse, "Ping should return true");
}
@Test @Test
@Order(2) @Order(2)
public void testListModelsAPI() public void testListModelsAPI()

View File

@ -3,40 +3,66 @@ package io.github.ollama4j.unittests.jackson;
import io.github.ollama4j.models.response.Model; import io.github.ollama4j.models.response.Model;
import org.junit.jupiter.api.Test; import org.junit.jupiter.api.Test;
import static org.junit.jupiter.api.Assertions.*;
public class TestModelRequestSerialization extends AbstractSerializationTest<Model> { public class TestModelRequestSerialization extends AbstractSerializationTest<Model> {
@Test @Test
public void testDeserializationOfModelResponseWithOffsetTime() { public void testDeserializationOfModelResponseWithOffsetTime() {
String serializedTestStringWithOffsetTime = "{\n" String serializedTestStringWithOffsetTime = "{\n" +
+ "\"name\": \"codellama:13b\",\n" " \"name\": \"codellama:13b\",\n" +
+ "\"modified_at\": \"2023-11-04T14:56:49.277302595-07:00\",\n" " \"modified_at\": \"2023-11-04T14:56:49.277302595-07:00\",\n" +
+ "\"size\": 7365960935,\n" " \"size\": 7365960935,\n" +
+ "\"digest\": \"9f438cb9cd581fc025612d27f7c1a6669ff83a8bb0ed86c94fcf4c5440555697\",\n" " \"digest\": \"9f438cb9cd581fc025612d27f7c1a6669ff83a8bb0ed86c94fcf4c5440555697\",\n" +
+ "\"details\": {\n" " \"details\": {\n" +
+ "\"format\": \"gguf\",\n" " \"format\": \"gguf\",\n" +
+ "\"family\": \"llama\",\n" " \"family\": \"llama\",\n" +
+ "\"families\": null,\n" " \"families\": null,\n" +
+ "\"parameter_size\": \"13B\",\n" " \"parameter_size\": \"13B\",\n" +
+ "\"quantization_level\": \"Q4_0\"\n" " \"quantization_level\": \"Q4_0\"\n" +
+ "}}"; " }\n" +
deserialize(serializedTestStringWithOffsetTime,Model.class); "}";
Model model = deserialize(serializedTestStringWithOffsetTime, Model.class);
assertNotNull(model);
assertEquals("codellama:13b", model.getName());
assertEquals("2023-11-04T21:56:49.277302595Z", model.getModifiedAt().toString());
assertEquals(7365960935L, model.getSize());
assertEquals("9f438cb9cd581fc025612d27f7c1a6669ff83a8bb0ed86c94fcf4c5440555697", model.getDigest());
assertNotNull(model.getModelMeta());
assertEquals("gguf", model.getModelMeta().getFormat());
assertEquals("llama", model.getModelMeta().getFamily());
assertNull(model.getModelMeta().getFamilies());
assertEquals("13B", model.getModelMeta().getParameterSize());
assertEquals("Q4_0", model.getModelMeta().getQuantizationLevel());
} }
@Test @Test
public void testDeserializationOfModelResponseWithZuluTime() { public void testDeserializationOfModelResponseWithZuluTime() {
String serializedTestStringWithZuluTimezone = "{\n" String serializedTestStringWithZuluTimezone = "{\n" +
+ "\"name\": \"codellama:13b\",\n" " \"name\": \"codellama:13b\",\n" +
+ "\"modified_at\": \"2023-11-04T14:56:49.277302595Z\",\n" " \"modified_at\": \"2023-11-04T14:56:49.277302595Z\",\n" +
+ "\"size\": 7365960935,\n" " \"size\": 7365960935,\n" +
+ "\"digest\": \"9f438cb9cd581fc025612d27f7c1a6669ff83a8bb0ed86c94fcf4c5440555697\",\n" " \"digest\": \"9f438cb9cd581fc025612d27f7c1a6669ff83a8bb0ed86c94fcf4c5440555697\",\n" +
+ "\"details\": {\n" " \"details\": {\n" +
+ "\"format\": \"gguf\",\n" " \"format\": \"gguf\",\n" +
+ "\"family\": \"llama\",\n" " \"family\": \"llama\",\n" +
+ "\"families\": null,\n" " \"families\": null,\n" +
+ "\"parameter_size\": \"13B\",\n" " \"parameter_size\": \"13B\",\n" +
+ "\"quantization_level\": \"Q4_0\"\n" " \"quantization_level\": \"Q4_0\"\n" +
+ "}}"; " }\n" +
deserialize(serializedTestStringWithZuluTimezone,Model.class); "}";
Model model = deserialize(serializedTestStringWithZuluTimezone, Model.class);
assertNotNull(model);
assertEquals("codellama:13b", model.getName());
assertEquals("2023-11-04T14:56:49.277302595Z", model.getModifiedAt().toString());
assertEquals(7365960935L, model.getSize());
assertEquals("9f438cb9cd581fc025612d27f7c1a6669ff83a8bb0ed86c94fcf4c5440555697", model.getDigest());
assertNotNull(model.getModelMeta());
assertEquals("gguf", model.getModelMeta().getFormat());
assertEquals("llama", model.getModelMeta().getFamily());
assertNull(model.getModelMeta().getFamilies());
assertEquals("13B", model.getModelMeta().getParameterSize());
assertEquals("Q4_0", model.getModelMeta().getQuantizationLevel());
} }
} }