Ollama4j
A Java library (wrapper/binding) for Ollama server.
Loading...
Searching...
No Matches
OllamaChatEndpointCaller.java
Go to the documentation of this file.
1package io.github.ollama4j.models.request;
2
3import com.fasterxml.jackson.core.JsonProcessingException;
4import com.fasterxml.jackson.core.type.TypeReference;
5import io.github.ollama4j.exceptions.OllamaBaseException;
6import io.github.ollama4j.models.chat.*;
7import io.github.ollama4j.models.generate.OllamaTokenHandler;
8import io.github.ollama4j.models.response.OllamaErrorResponse;
9import io.github.ollama4j.utils.Utils;
10import org.slf4j.Logger;
11import org.slf4j.LoggerFactory;
12
13import java.io.BufferedReader;
14import java.io.IOException;
15import java.io.InputStream;
16import java.io.InputStreamReader;
17import java.net.URI;
18import java.net.http.HttpClient;
19import java.net.http.HttpRequest;
20import java.net.http.HttpResponse;
21import java.nio.charset.StandardCharsets;
22import java.util.List;
23
28
29 private static final Logger LOG = LoggerFactory.getLogger(OllamaChatEndpointCaller.class);
30
31 private OllamaTokenHandler tokenHandler;
32
33 public OllamaChatEndpointCaller(String host, BasicAuth basicAuth, long requestTimeoutSeconds, boolean verbose) {
34 super(host, basicAuth, requestTimeoutSeconds, verbose);
35 }
36
37 @Override
38 protected String getEndpointSuffix() {
39 return "/api/chat";
40 }
41
53 @Override
54 protected boolean parseResponseAndAddToBuffer(String line, StringBuilder responseBuffer) {
55 try {
56 OllamaChatResponseModel ollamaResponseModel = Utils.getObjectMapper().readValue(line, OllamaChatResponseModel.class);
57 // it seems that under heavy load ollama responds with an empty chat message part in the streamed response
58 // thus, we null check the message and hope that the next streamed response has some message content again
59 OllamaChatMessage message = ollamaResponseModel.getMessage();
60 if(message != null) {
61 responseBuffer.append(message.getContent());
62 if (tokenHandler != null) {
63 tokenHandler.accept(ollamaResponseModel);
64 }
65 }
66 return ollamaResponseModel.isDone();
67 } catch (JsonProcessingException e) {
68 LOG.error("Error parsing the Ollama chat response!", e);
69 return true;
70 }
71 }
72
74 throws OllamaBaseException, IOException, InterruptedException {
75 this.tokenHandler = tokenHandler;
76 return callSync(body);
77 }
78
79 public OllamaChatResult callSync(OllamaChatRequest body) throws OllamaBaseException, IOException, InterruptedException {
80 // Create Request
81 HttpClient httpClient = HttpClient.newHttpClient();
82 URI uri = URI.create(getHost() + getEndpointSuffix());
83 HttpRequest.Builder requestBuilder =
85 .POST(
86 body.getBodyPublisher());
87 HttpRequest request = requestBuilder.build();
88 if (isVerbose()) LOG.info("Asking model: " + body);
89 HttpResponse<InputStream> response =
90 httpClient.send(request, HttpResponse.BodyHandlers.ofInputStream());
91
92 int statusCode = response.statusCode();
93 InputStream responseBodyStream = response.body();
94 StringBuilder responseBuffer = new StringBuilder();
95 OllamaChatResponseModel ollamaChatResponseModel = null;
96 List<OllamaChatToolCalls> wantedToolsForStream = null;
97 try (BufferedReader reader =
98 new BufferedReader(new InputStreamReader(responseBodyStream, StandardCharsets.UTF_8))) {
99
100 String line;
101 while ((line = reader.readLine()) != null) {
102 if (statusCode == 404) {
103 LOG.warn("Status code: 404 (Not Found)");
104 OllamaErrorResponse ollamaResponseModel =
105 Utils.getObjectMapper().readValue(line, OllamaErrorResponse.class);
106 responseBuffer.append(ollamaResponseModel.getError());
107 } else if (statusCode == 401) {
108 LOG.warn("Status code: 401 (Unauthorized)");
109 OllamaErrorResponse ollamaResponseModel =
111 .readValue("{\"error\":\"Unauthorized\"}", OllamaErrorResponse.class);
112 responseBuffer.append(ollamaResponseModel.getError());
113 } else if (statusCode == 400) {
114 LOG.warn("Status code: 400 (Bad Request)");
115 OllamaErrorResponse ollamaResponseModel = Utils.getObjectMapper().readValue(line,
116 OllamaErrorResponse.class);
117 responseBuffer.append(ollamaResponseModel.getError());
118 } else {
119 boolean finished = parseResponseAndAddToBuffer(line, responseBuffer);
120 ollamaChatResponseModel = Utils.getObjectMapper().readValue(line, OllamaChatResponseModel.class);
121 if(body.stream && ollamaChatResponseModel.getMessage().getToolCalls() != null){
122 wantedToolsForStream = ollamaChatResponseModel.getMessage().getToolCalls();
123 }
124 if (finished && body.stream) {
125 ollamaChatResponseModel.getMessage().setContent(responseBuffer.toString());
126 break;
127 }
128 }
129 }
130 }
131 if (statusCode != 200) {
132 LOG.error("Status code " + statusCode);
133 throw new OllamaBaseException(responseBuffer.toString());
134 } else {
135 if(wantedToolsForStream != null) {
136 ollamaChatResponseModel.getMessage().setToolCalls(wantedToolsForStream);
137 }
138 OllamaChatResult ollamaResult =
139 new OllamaChatResult(ollamaChatResponseModel,body.getMessages());
140 if (isVerbose()) LOG.info("Model response: " + ollamaResult);
141 return ollamaResult;
142 }
143 }
144}
OllamaChatResult call(OllamaChatRequest body, OllamaTokenHandler tokenHandler)
OllamaChatEndpointCaller(String host, BasicAuth basicAuth, long requestTimeoutSeconds, boolean verbose)
boolean parseResponseAndAddToBuffer(String line, StringBuilder responseBuffer)
OllamaEndpointCaller(String host, BasicAuth basicAuth, long requestTimeoutSeconds, boolean verbose)
static ObjectMapper getObjectMapper()
Definition Utils.java:17