1package io.github.ollama4j;
3import com.fasterxml.jackson.core.JsonParseException;
4import com.fasterxml.jackson.databind.JsonNode;
5import com.fasterxml.jackson.databind.ObjectMapper;
6import io.github.ollama4j.exceptions.OllamaBaseException;
7import io.github.ollama4j.exceptions.RoleNotFoundException;
8import io.github.ollama4j.exceptions.ToolInvocationException;
9import io.github.ollama4j.exceptions.ToolNotFoundException;
10import io.github.ollama4j.models.chat.*;
11import io.github.ollama4j.models.embeddings.OllamaEmbedRequestModel;
12import io.github.ollama4j.models.embeddings.OllamaEmbedResponseModel;
13import io.github.ollama4j.models.embeddings.OllamaEmbeddingResponseModel;
14import io.github.ollama4j.models.embeddings.OllamaEmbeddingsRequestModel;
15import io.github.ollama4j.models.generate.OllamaGenerateRequest;
16import io.github.ollama4j.models.generate.OllamaStreamHandler;
17import io.github.ollama4j.models.generate.OllamaTokenHandler;
18import io.github.ollama4j.models.ps.ModelsProcessResponse;
19import io.github.ollama4j.models.request.*;
20import io.github.ollama4j.models.response.*;
21import io.github.ollama4j.tools.*;
22import io.github.ollama4j.tools.annotations.OllamaToolService;
23import io.github.ollama4j.tools.annotations.ToolProperty;
24import io.github.ollama4j.tools.annotations.ToolSpec;
25import io.github.ollama4j.utils.Constants;
26import io.github.ollama4j.utils.Options;
27import io.github.ollama4j.utils.Utils;
29import org.jsoup.Jsoup;
30import org.jsoup.nodes.Document;
31import org.jsoup.nodes.Element;
32import org.jsoup.select.Elements;
33import org.slf4j.Logger;
34import org.slf4j.LoggerFactory;
37import java.lang.reflect.InvocationTargetException;
38import java.lang.reflect.Method;
39import java.lang.reflect.Parameter;
41import java.net.URISyntaxException;
42import java.net.http.HttpClient;
43import java.net.http.HttpConnectTimeoutException;
44import java.net.http.HttpRequest;
45import java.net.http.HttpResponse;
46import java.nio.charset.StandardCharsets;
47import java.nio.file.Files;
48import java.time.Duration;
50import java.util.stream.Collectors;
55@SuppressWarnings({
"DuplicatedCode",
"resource"})
58 private static final Logger logger = LoggerFactory.getLogger(
OllamaAPI.class);
60 private final String host;
72 private long requestTimeoutSeconds = 10;
82 private boolean verbose =
true;
92 private int maxChatToolCallRetries = 3;
104 @SuppressWarnings({
"FieldMayBeFinal",
"FieldCanBeLocal"})
105 private int numberOfRetriesForModelPull = 0;
112 this.host =
"http://localhost:11434";
121 if (host.endsWith(
"/")) {
122 this.host = host.substring(0, host.length() - 1);
127 logger.info(
"Ollama API initialized with host: {}", this.host);
139 this.auth =
new BasicAuth(username, password);
158 String url = this.host +
"/api/tags";
159 HttpClient httpClient = HttpClient.newHttpClient();
160 HttpRequest httpRequest;
162 httpRequest = getRequestBuilderDefault(
new URI(url))
167 }
catch (URISyntaxException e) {
168 throw new RuntimeException(e);
172 response = httpClient.send(httpRequest, HttpResponse.BodyHandlers.ofString());
173 }
catch (HttpConnectTimeoutException e) {
175 }
catch (IOException | InterruptedException e) {
176 throw new RuntimeException(e);
178 int statusCode =
response.statusCode();
179 return statusCode == 200;
192 String url = this.host +
"/api/ps";
193 HttpClient httpClient = HttpClient.newHttpClient();
194 HttpRequest httpRequest =
null;
196 httpRequest = getRequestBuilderDefault(
new URI(url))
200 }
catch (URISyntaxException e) {
201 throw new RuntimeException(e);
203 HttpResponse<String>
response =
null;
204 response = httpClient.send(httpRequest, HttpResponse.BodyHandlers.ofString());
205 int statusCode =
response.statusCode();
206 String responseString =
response.body();
207 if (statusCode == 200) {
224 String url = this.host +
"/api/tags";
225 HttpClient httpClient = HttpClient.newHttpClient();
226 HttpRequest httpRequest = getRequestBuilderDefault(
new URI(url))
230 HttpResponse<String>
response = httpClient.send(httpRequest, HttpResponse.BodyHandlers.ofString());
231 int statusCode =
response.statusCode();
232 String responseString =
response.body();
233 if (statusCode == 200) {
259 String url =
"https://ollama.com/library";
260 HttpClient httpClient = HttpClient.newHttpClient();
261 HttpRequest httpRequest = getRequestBuilderDefault(
new URI(url))
265 HttpResponse<String>
response = httpClient.send(httpRequest, HttpResponse.BodyHandlers.ofString());
266 int statusCode =
response.statusCode();
267 String responseString =
response.body();
268 List<LibraryModel> models =
new ArrayList<>();
269 if (statusCode == 200) {
270 Document doc = Jsoup.parse(responseString);
271 Elements modelSections = doc.selectXpath(
"//*[@id='repo']/ul/li/a");
272 for (Element e : modelSections) {
274 Elements names = e.select(
"div > h2 > div > span");
275 Elements desc = e.select(
"div > p");
276 Elements pullCounts = e.select(
"div:nth-of-type(2) > p > span:first-of-type > span:first-of-type");
277 Elements popularTags = e.select(
"div > div > span");
278 Elements totalTags = e.select(
"div:nth-of-type(2) > p > span:nth-of-type(2) > span:first-of-type");
279 Elements lastUpdatedTime = e
280 .select(
"div:nth-of-type(2) > p > span:nth-of-type(3) > span:nth-of-type(2)");
282 if (names.first() ==
null || names.isEmpty()) {
286 Optional.ofNullable(names.first()).map(Element::text).ifPresent(model::setName);
287 model.setDescription(Optional.ofNullable(desc.first()).map(Element::text).orElse(
""));
288 model.setPopularTags(Optional.of(popularTags)
289 .map(tags -> tags.stream().map(Element::text).collect(Collectors.toList()))
290 .orElse(
new ArrayList<>()));
291 model.setPullCount(Optional.ofNullable(pullCounts.first()).map(Element::text).orElse(
""));
293 Optional.ofNullable(totalTags.first()).map(Element::text).map(Integer::parseInt).orElse(0));
294 model.setLastUpdated(Optional.ofNullable(lastUpdatedTime.first()).map(Element::text).orElse(
""));
328 String url = String.format(
"https://ollama.com/library/%s/tags", libraryModel.getName());
329 HttpClient httpClient = HttpClient.newHttpClient();
330 HttpRequest httpRequest = getRequestBuilderDefault(
new URI(url))
334 HttpResponse<String>
response = httpClient.send(httpRequest, HttpResponse.BodyHandlers.ofString());
335 int statusCode =
response.statusCode();
336 String responseString =
response.body();
338 List<LibraryModelTag> libraryModelTags =
new ArrayList<>();
339 if (statusCode == 200) {
340 Document doc = Jsoup.parse(responseString);
341 Elements tagSections = doc
342 .select(
"html > body > main > div > section > div > div > div:nth-child(n+2) > div");
343 for (Element e : tagSections) {
344 Elements tags = e.select(
"div > a > div");
345 Elements tagsMetas = e.select(
"div > span");
349 if (tags.first() ==
null || tags.isEmpty()) {
353 libraryModelTag.setName(libraryModel.getName());
354 Optional.ofNullable(tags.first()).map(Element::text).ifPresent(libraryModelTag::setTag);
355 libraryModelTag.setSize(Optional.ofNullable(tagsMetas.first()).map(element -> element.text().split(
"•"))
356 .filter(parts -> parts.length > 1).map(parts -> parts[1].trim()).orElse(
""));
358 .setLastUpdated(Optional.ofNullable(tagsMetas.first()).map(element -> element.text().split(
"•"))
359 .filter(parts -> parts.length > 1).map(parts -> parts[2].trim()).orElse(
""));
360 libraryModelTags.add(libraryModelTag);
363 libraryModelDetail.setModel(libraryModel);
364 libraryModelDetail.setTags(libraryModelTags);
365 return libraryModelDetail;
407 LibraryModel libraryModel = libraryModels.stream().filter(model -> model.getName().equals(modelName))
408 .findFirst().orElseThrow(
409 () ->
new NoSuchElementException(String.format(
"Model by name '%s' not found", modelName)));
411 return libraryModelDetail.getTags().stream().filter(tagName -> tagName.getTag().equals(tag)).findFirst()
412 .orElseThrow(() ->
new NoSuchElementException(
413 String.format(
"Tag '%s' for model '%s' not found", tag, modelName)));
439 if (numberOfRetriesForModelPull == 0) {
440 this.doPullModel(modelName);
443 int numberOfRetries = 0;
444 long baseDelayMillis = 3000L;
445 while (numberOfRetries < numberOfRetriesForModelPull) {
447 this.doPullModel(modelName);
450 handlePullRetry(modelName, numberOfRetries, numberOfRetriesForModelPull, baseDelayMillis);
455 "Failed to pull model " + modelName +
" after " + numberOfRetriesForModelPull +
" retries");
461 private void handlePullRetry(String modelName,
int currentRetry,
int maxRetries,
long baseDelayMillis)
462 throws InterruptedException {
463 int attempt = currentRetry + 1;
464 if (attempt < maxRetries) {
465 long backoffMillis = baseDelayMillis * (1L << currentRetry);
466 logger.error(
"Failed to pull model {}, retrying in {}s... (attempt {}/{})",
467 modelName, backoffMillis / 1000, attempt, maxRetries);
469 Thread.sleep(backoffMillis);
470 }
catch (InterruptedException ie) {
471 Thread.currentThread().interrupt();
475 logger.error(
"Failed to pull model {} after {} attempts, no more retries.", modelName, maxRetries);
479 private void doPullModel(String modelName)
481 String url = this.host +
"/api/pull";
482 String jsonData =
new ModelRequest(modelName).toString();
483 HttpRequest request = getRequestBuilderDefault(
new URI(url)).POST(HttpRequest.BodyPublishers.ofString(jsonData))
487 HttpClient client = HttpClient.newHttpClient();
488 HttpResponse<InputStream> response = client.send(request, HttpResponse.BodyHandlers.ofInputStream());
489 int statusCode = response.statusCode();
490 InputStream responseBodyStream = response.body();
491 String responseString =
"";
492 boolean success =
false;
493 try (BufferedReader reader =
new BufferedReader(
494 new InputStreamReader(responseBodyStream, StandardCharsets.UTF_8))) {
496 while ((line = reader.readLine()) !=
null) {
497 ModelPullResponse modelPullResponse =
Utils.
getObjectMapper().readValue(line, ModelPullResponse.class);
498 if (modelPullResponse !=
null) {
500 if (modelPullResponse.getError() !=
null && !modelPullResponse.getError().trim().isEmpty()) {
504 if (modelPullResponse.getStatus() !=
null) {
506 logger.info(
"{}: {}", modelName, modelPullResponse.getStatus());
509 if (
"success".equalsIgnoreCase(modelPullResponse.getStatus())) {
514 logger.error(
"Received null response for model pull.");
519 logger.error(
"Model pull failed or returned invalid status.");
522 if (statusCode != 200) {
528 String url = this.host +
"/api/version";
529 HttpClient httpClient = HttpClient.newHttpClient();
530 HttpRequest httpRequest = getRequestBuilderDefault(
new URI(url))
534 HttpResponse<String>
response = httpClient.send(httpRequest, HttpResponse.BodyHandlers.ofString());
535 int statusCode =
response.statusCode();
536 String responseString =
response.body();
537 if (statusCode == 200) {
560 String tagToPull = String.format(
"%s:%s", libraryModelTag.getName(), libraryModelTag.getTag());
576 String url = this.host +
"/api/show";
578 HttpRequest
request = getRequestBuilderDefault(
new URI(url))
581 .POST(HttpRequest.BodyPublishers.ofString(jsonData)).build();
582 HttpClient client = HttpClient.newHttpClient();
583 HttpResponse<String>
response = client.send(
request, HttpResponse.BodyHandlers.ofString());
584 int statusCode =
response.statusCode();
585 String responseBody =
response.body();
586 if (statusCode == 200) {
609 String url = this.host +
"/api/create";
611 HttpRequest
request = getRequestBuilderDefault(
new URI(url))
614 .POST(HttpRequest.BodyPublishers.ofString(jsonData, StandardCharsets.UTF_8)).build();
615 HttpClient client = HttpClient.newHttpClient();
616 HttpResponse<String>
response = client.send(
request, HttpResponse.BodyHandlers.ofString());
617 int statusCode =
response.statusCode();
618 String responseString =
response.body();
619 if (statusCode != 200) {
625 if (responseString.contains(
"error")) {
629 logger.info(responseString);
650 String url = this.host +
"/api/create";
652 HttpRequest
request = getRequestBuilderDefault(
new URI(url))
655 .POST(HttpRequest.BodyPublishers.ofString(jsonData, StandardCharsets.UTF_8)).build();
656 HttpClient client = HttpClient.newHttpClient();
657 HttpResponse<String>
response = client.send(
request, HttpResponse.BodyHandlers.ofString());
658 int statusCode =
response.statusCode();
659 String responseString =
response.body();
660 if (statusCode != 200) {
663 if (responseString.contains(
"error")) {
667 logger.info(responseString);
684 String url = this.host +
"/api/create";
685 String jsonData = customModelRequest.toString();
686 HttpRequest
request = getRequestBuilderDefault(
new URI(url))
689 .POST(HttpRequest.BodyPublishers.ofString(jsonData, StandardCharsets.UTF_8)).build();
690 HttpClient client = HttpClient.newHttpClient();
691 HttpResponse<String>
response = client.send(
request, HttpResponse.BodyHandlers.ofString());
692 int statusCode =
response.statusCode();
693 String responseString =
response.body();
694 if (statusCode != 200) {
697 if (responseString.contains(
"error")) {
701 logger.info(responseString);
716 public void deleteModel(String modelName,
boolean ignoreIfNotPresent)
718 String url = this.host +
"/api/delete";
720 HttpRequest
request = getRequestBuilderDefault(
new URI(url))
721 .method(
"DELETE", HttpRequest.BodyPublishers.ofString(jsonData, StandardCharsets.UTF_8))
725 HttpClient client = HttpClient.newHttpClient();
726 HttpResponse<String>
response = client.send(
request, HttpResponse.BodyHandlers.ofString());
727 int statusCode =
response.statusCode();
728 String responseBody =
response.body();
729 if (statusCode == 404 && responseBody.contains(
"model") && responseBody.contains(
"not found")) {
732 if (statusCode != 200) {
767 URI uri = URI.create(this.host +
"/api/embeddings");
768 String jsonData = modelRequest.toString();
769 HttpClient httpClient = HttpClient.newHttpClient();
770 HttpRequest.Builder requestBuilder = getRequestBuilderDefault(uri)
772 .POST(HttpRequest.BodyPublishers.ofString(jsonData));
773 HttpRequest
request = requestBuilder.build();
774 HttpResponse<String>
response = httpClient.send(
request, HttpResponse.BodyHandlers.ofString());
775 int statusCode =
response.statusCode();
776 String responseBody =
response.body();
777 if (statusCode == 200) {
780 return embeddingResponse.getEmbedding();
812 URI uri = URI.create(this.host +
"/api/embed");
814 HttpClient httpClient = HttpClient.newHttpClient();
816 HttpRequest
request = HttpRequest.newBuilder(uri)
818 .POST(HttpRequest.BodyPublishers.ofString(jsonData)).build();
820 HttpResponse<String>
response = httpClient.send(
request, HttpResponse.BodyHandlers.ofString());
821 int statusCode =
response.statusCode();
822 String responseBody =
response.body();
824 if (statusCode == 200) {
860 ollamaRequestModel.setRaw(raw);
861 ollamaRequestModel.setThink(
false);
862 ollamaRequestModel.setOptions(options.getOptionsMap());
863 return generateSyncForOllamaRequestModel(ollamaRequestModel,
null, responseStreamHandler);
897 ollamaRequestModel.setRaw(raw);
898 ollamaRequestModel.setThink(
true);
899 ollamaRequestModel.setOptions(options.getOptionsMap());
900 return generateSyncForOllamaRequestModel(ollamaRequestModel, thinkingStreamHandler, responseStreamHandler);
929 return generate(model, prompt, raw, options,
null,
null);
931 return generate(model, prompt, raw, options,
null);
951 @SuppressWarnings(
"LoggingSimilarMessage")
954 URI uri = URI.create(this.host +
"/api/generate");
956 Map<String, Object> requestBody =
new HashMap<>();
957 requestBody.put(
"model", model);
958 requestBody.put(
"prompt", prompt);
959 requestBody.put(
"stream",
false);
960 requestBody.put(
"format", format);
963 HttpClient httpClient = HttpClient.newHttpClient();
965 HttpRequest
request = getRequestBuilderDefault(uri)
968 .POST(HttpRequest.BodyPublishers.ofString(jsonData)).build();
974 logger.info(
"Asking model:\n{}", prettyJson);
975 }
catch (Exception e) {
976 logger.info(
"Asking model: {}", jsonData);
979 HttpResponse<String>
response = httpClient.send(
request, HttpResponse.BodyHandlers.ofString());
980 int statusCode =
response.statusCode();
981 String responseBody =
response.body();
982 if (statusCode == 200) {
986 structuredResult.getResponseTime(), statusCode);
988 ollamaResult.setModel(structuredResult.getModel());
989 ollamaResult.setCreatedAt(structuredResult.getCreatedAt());
990 ollamaResult.setDone(structuredResult.isDone());
991 ollamaResult.setDoneReason(structuredResult.getDoneReason());
992 ollamaResult.setContext(structuredResult.getContext());
993 ollamaResult.setTotalDuration(structuredResult.getTotalDuration());
994 ollamaResult.setLoadDuration(structuredResult.getLoadDuration());
995 ollamaResult.setPromptEvalCount(structuredResult.getPromptEvalCount());
996 ollamaResult.setPromptEvalDuration(structuredResult.getPromptEvalDuration());
997 ollamaResult.setEvalCount(structuredResult.getEvalCount());
998 ollamaResult.setEvalDuration(structuredResult.getEvalDuration());
1000 logger.info(
"Model response:\n{}", ollamaResult);
1002 return ollamaResult;
1005 logger.info(
"Model response:\n{}",
1033 Map<ToolFunctionCallSpec, Object> toolResults =
new HashMap<>();
1035 if (!prompt.startsWith(
"[AVAILABLE_TOOLS]")) {
1038 promptBuilder.withToolSpecification(spec);
1040 promptBuilder.withPrompt(prompt);
1041 prompt = promptBuilder.build();
1045 toolResult.setModelResult(result);
1047 String toolsResponse = result.getResponse();
1048 if (toolsResponse.contains(
"[TOOL_CALLS]")) {
1049 toolsResponse = toolsResponse.replace(
"[TOOL_CALLS]",
"");
1052 List<ToolFunctionCallSpec> toolFunctionCallSpecs =
new ArrayList<>();
1055 if (!toolsResponse.isEmpty()) {
1058 JsonNode jsonNode = objectMapper.readTree(toolsResponse);
1059 }
catch (JsonParseException e) {
1060 logger.warn(
"Response from model does not contain any tool calls. Returning the response as is.");
1063 toolFunctionCallSpecs = objectMapper.readValue(toolsResponse,
1064 objectMapper.getTypeFactory().constructCollectionType(List.class,
ToolFunctionCallSpec.class));
1067 toolResults.put(toolFunctionCallSpec, invokeTool(toolFunctionCallSpec));
1069 toolResult.setToolResults(toolResults);
1113 ollamaRequestModel.setRaw(raw);
1114 ollamaRequestModel.setThink(think);
1115 URI uri = URI.create(this.host +
"/api/generate");
1117 getRequestBuilderDefault(uri), ollamaRequestModel, requestTimeoutSeconds);
1118 ollamaAsyncResultStreamer.start();
1119 return ollamaAsyncResultStreamer;
1144 List<String> images =
new ArrayList<>();
1145 for (File imageFile : imageFiles) {
1146 images.add(encodeFileToBase64(imageFile));
1149 ollamaRequestModel.setOptions(options.getOptionsMap());
1150 return generateSyncForOllamaRequestModel(ollamaRequestModel,
null, streamHandler);
1192 List<String> images =
new ArrayList<>();
1193 for (String imageURL : imageURLs) {
1197 ollamaRequestModel.setOptions(options.getOptionsMap());
1198 return generateSyncForOllamaRequestModel(ollamaRequestModel,
null, streamHandler);
1239 List<String> encodedImages =
new ArrayList<>();
1240 for (
byte[] image : images) {
1241 encodedImages.add(encodeByteArrayToBase64(image));
1244 ollamaRequestModel.setOptions(options.getOptionsMap());
1245 return generateSyncForOllamaRequestModel(ollamaRequestModel,
null, streamHandler);
1369 request.setTools(toolRegistry.getRegisteredSpecs().stream().map(
Tools.ToolSpecification::getToolPrompt)
1370 .collect(Collectors.toList()));
1372 if (tokenHandler !=
null) {
1374 result = requestCaller.
call(
request, tokenHandler);
1380 List<OllamaChatToolCalls> toolCalls = result.getResponseModel().getMessage().getToolCalls();
1381 int toolCallTries = 0;
1382 while (toolCalls !=
null && !toolCalls.isEmpty() && toolCallTries < maxChatToolCallRetries) {
1384 String toolName = toolCall.getFunction().getName();
1385 ToolFunction toolFunction = toolRegistry.getToolFunction(toolName);
1386 if (toolFunction ==
null) {
1389 Map<String, Object> arguments = toolCall.getFunction().getArguments();
1390 Object res = toolFunction.
apply(arguments);
1391 String argumentKeys = arguments.keySet().stream()
1392 .map(Object::toString)
1393 .collect(Collectors.joining(
", "));
1395 "[TOOL_RESULTS] " + toolName +
"(" + argumentKeys +
"): " + res +
" [/TOOL_RESULTS]"));
1398 if (tokenHandler !=
null) {
1399 result = requestCaller.
call(
request, tokenHandler);
1403 toolCalls = result.getResponseModel().getMessage().getToolCalls();
1419 toolRegistry.addTool(toolSpecification.getFunctionName(), toolSpecification);
1421 logger.debug(
"Registered tool: {}", toolSpecification.getFunctionName());
1437 toolRegistry.addTool(toolSpecification.getFunctionName(), toolSpecification);
1446 toolRegistry.clear();
1448 logger.debug(
"All tools have been deregistered.");
1466 Class<?> callerClass =
null;
1468 callerClass = Class.forName(Thread.currentThread().getStackTrace()[2].getClassName());
1469 }
catch (ClassNotFoundException e) {
1470 throw new RuntimeException(e);
1474 if (ollamaToolServiceAnnotation ==
null) {
1475 throw new IllegalStateException(callerClass +
" is not annotated as " +
OllamaToolService.class);
1478 Class<?>[] providers = ollamaToolServiceAnnotation.
providers();
1479 for (Class<?> provider : providers) {
1482 }
catch (InstantiationException | NoSuchMethodException | IllegalAccessException
1483 | InvocationTargetException e) {
1484 throw new RuntimeException(e);
1502 Class<?> objectClass =
object.getClass();
1503 Method[] methods = objectClass.getMethods();
1504 for (Method m : methods) {
1506 if (toolSpec ==
null) {
1509 String operationName = !toolSpec.
name().isBlank() ? toolSpec.
name() : m.getName();
1510 String operationDesc = !toolSpec.
desc().isBlank() ? toolSpec.
desc() : operationName;
1513 LinkedHashMap<String, String> methodParams =
new LinkedHashMap<>();
1514 for (Parameter parameter : m.getParameters()) {
1516 String propType = parameter.getType().getTypeName();
1517 if (toolPropertyAnn ==
null) {
1518 methodParams.put(parameter.getName(),
null);
1521 String propName = !toolPropertyAnn.
name().isBlank() ? toolPropertyAnn.
name() : parameter.getName();
1522 methodParams.put(propName, propType);
1524 .description(toolPropertyAnn.
desc()).required(toolPropertyAnn.
required()).build());
1527 List<String> reqProps = params.entrySet().stream().filter(e -> e.getValue().isRequired())
1528 .map(Map.Entry::getKey).collect(Collectors.toList());
1530 Tools.ToolSpecification toolSpecification =
Tools.
ToolSpecification.builder().functionName(operationName)
1531 .functionDescription(operationDesc)
1535 .builder().type(
"object").properties(params).required(reqProps).build())
1541 toolSpecification.setToolFunction(reflectionalToolFunction);
1542 toolRegistry.addTool(toolSpecification.getFunctionName(), toolSpecification);
1587 private static String encodeFileToBase64(File file)
throws IOException {
1588 return Base64.getEncoder().encodeToString(Files.readAllBytes(file.toPath()));
1597 private static String encodeByteArrayToBase64(
byte[] bytes) {
1598 return Base64.getEncoder().encodeToString(bytes);
1627 if (responseStreamHandler !=
null) {
1628 ollamaRequestModel.setStream(
true);
1629 result = requestCaller.
call(ollamaRequestModel, thinkingStreamHandler, responseStreamHandler);
1631 result = requestCaller.
callSync(ollamaRequestModel);
1642 private HttpRequest.Builder getRequestBuilderDefault(URI uri) {
1643 HttpRequest.Builder requestBuilder = HttpRequest.newBuilder(uri)
1645 .timeout(Duration.ofSeconds(requestTimeoutSeconds));
1646 if (isBasicAuthCredentialsSet()) {
1649 return requestBuilder;
1657 private boolean isBasicAuthCredentialsSet() {
1658 return auth !=
null;
1663 String methodName = toolFunctionCallSpec.getName();
1664 Map<String, Object> arguments = toolFunctionCallSpec.getArguments();
1667 logger.debug(
"Invoking function {} with arguments {}", methodName, arguments);
1669 if (
function ==
null) {
1671 "No such tool: " + methodName +
". Please register the tool before invoking it.");
1673 return function.
apply(arguments);
1674 }
catch (Exception e) {
OllamaResult generateWithImageFiles(String model, String prompt, List< File > imageFiles, Options options, OllamaStreamHandler streamHandler)
OllamaChatResult chat(OllamaChatRequest request)
ModelDetail getModelDetails(String modelName)
List< Double > generateEmbeddings(OllamaEmbeddingsRequestModel modelRequest)
List< Model > listModels()
void setBearerAuth(String bearerToken)
OllamaResult generate(String model, String prompt, boolean raw, Options options, OllamaStreamHandler thinkingStreamHandler, OllamaStreamHandler responseStreamHandler)
OllamaResult generateWithImages(String model, String prompt, List< byte[]> images, Options options, OllamaStreamHandler streamHandler)
OllamaChatResult chat(String model, List< OllamaChatMessage > messages)
OllamaAsyncResultStreamer generateAsync(String model, String prompt, boolean raw, boolean think)
List< Double > generateEmbeddings(String model, String prompt)
void pullModel(String modelName)
void setBasicAuth(String username, String password)
void deleteModel(String modelName, boolean ignoreIfNotPresent)
void createModelWithFilePath(String modelName, String modelFilePath)
ModelsProcessResponse ps()
LibraryModelTag findModelTagFromLibrary(String modelName, String tag)
OllamaChatMessageRole getRole(String roleName)
OllamaChatMessageRole addCustomRole(String roleName)
void pullModel(LibraryModelTag libraryModelTag)
OllamaResult generateWithImages(String model, String prompt, List< byte[]> images, Options options)
List< OllamaChatMessageRole > listRoles()
LibraryModelDetail getLibraryModelDetails(LibraryModel libraryModel)
OllamaResult generateWithImageURLs(String model, String prompt, List< String > imageURLs, Options options, OllamaStreamHandler streamHandler)
OllamaEmbedResponseModel embed(OllamaEmbedRequestModel modelRequest)
OllamaResult generate(String model, String prompt, boolean raw, boolean think, Options options)
void registerTool(Tools.ToolSpecification toolSpecification)
void registerAnnotatedTools(Object object)
void registerAnnotatedTools()
OllamaResult generate(String model, String prompt, boolean raw, Options options, OllamaStreamHandler responseStreamHandler)
List< LibraryModel > listModelsFromLibrary()
void registerTools(List< Tools.ToolSpecification > toolSpecifications)
OllamaChatResult chatStreaming(OllamaChatRequest request, OllamaTokenHandler tokenHandler)
OllamaToolsResult generateWithTools(String model, String prompt, Options options)
void createModel(CustomModelRequest customModelRequest)
OllamaChatResult chat(OllamaChatRequest request, OllamaStreamHandler thinkingStreamHandler, OllamaStreamHandler responseStreamHandler)
OllamaResult generateWithImageURLs(String model, String prompt, List< String > imageURLs, Options options)
OllamaEmbedResponseModel embed(String model, List< String > inputs)
void createModelWithModelFileContents(String modelName, String modelFileContents)
OllamaResult generateWithImageFiles(String model, String prompt, List< File > imageFiles, Options options)
static List< OllamaChatMessageRole > getRoles()
static OllamaChatMessageRole newCustomRole(String roleName)
static OllamaChatMessageRole getRole(String roleName)
static final OllamaChatMessageRole TOOL
OllamaChatRequestBuilder withMessages(List< OllamaChatMessage > messages)
OllamaChatRequest build()
static OllamaChatRequestBuilder getInstance(String model)
abstract String getAuthHeaderValue()
OllamaChatResult call(OllamaChatRequest body, OllamaTokenHandler tokenHandler)
OllamaChatResult callSync(OllamaChatRequest body)
OllamaResult call(OllamaRequestBody body, OllamaStreamHandler thinkingStreamHandler, OllamaStreamHandler responseStreamHandler)
OllamaResult callSync(OllamaRequestBody body)
static byte[] loadImageBytesFromUrl(String imageUrl)
static ObjectMapper getObjectMapper()