langchain4j-ollama get rid of lombok (#1658)

## Issue
#1636 

## Change
`langchain4j-ollama` get rid of `lombok`

## General checklist
- [x] There are no breaking changes
- [ ] I have added unit and integration tests for my change
- [x] I have manually run all the unit and integration tests in the
module I have added/changed, and they are all green
- [x] I have manually run all the unit and integration tests in the
[core](https://github.com/langchain4j/langchain4j/tree/main/langchain4j-core)
and
[main](https://github.com/langchain4j/langchain4j/tree/main/langchain4j)
modules, and they are all green
<!-- Before adding documentation and example(s) (below), please wait
until the PR is reviewed and approved. -->
- [ ] I have added/updated the
[documentation](https://github.com/langchain4j/langchain4j/tree/main/docs/docs)
- [ ] I have added an example in the [examples
repo](https://github.com/langchain4j/langchain4j-examples) (only for
"big" features)
- [ ] I have added/updated [Spring Boot
starter(s)](https://github.com/langchain4j/langchain4j-spring) (if
applicable)
This commit is contained in:
ZYinNJU 2024-09-10 19:49:53 +08:00 committed by GitHub
parent ff243b0ce0
commit 7c5e351486
No known key found for this signature in database
GPG Key ID: B5690EEEBB952194
34 changed files with 2238 additions and 267 deletions

View File

@ -50,12 +50,6 @@
</dependency>
<!-- DEPENDENCY CONFLICT RESOLUTION FOR OKHTTP (END) -->
<dependency>
<groupId>org.projectlombok</groupId>
<artifactId>lombok</artifactId>
<scope>provided</scope>
</dependency>
<dependency>
<groupId>org.junit.jupiter</groupId>
<artifactId>junit-jupiter-engine</artifactId>

View File

@ -4,19 +4,11 @@ import com.fasterxml.jackson.annotation.JsonIgnoreProperties;
import com.fasterxml.jackson.annotation.JsonInclude;
import com.fasterxml.jackson.databind.PropertyNamingStrategies.SnakeCaseStrategy;
import com.fasterxml.jackson.databind.annotation.JsonNaming;
import lombok.AllArgsConstructor;
import lombok.Builder;
import lombok.Data;
import lombok.NoArgsConstructor;
import java.util.List;
import static com.fasterxml.jackson.annotation.JsonInclude.Include.NON_NULL;
@Data
@NoArgsConstructor
@AllArgsConstructor
@Builder
@JsonIgnoreProperties(ignoreUnknown = true)
@JsonInclude(NON_NULL)
@JsonNaming(SnakeCaseStrategy.class)
@ -28,4 +20,113 @@ class ChatRequest {
private String format;
private Boolean stream;
private List<Tool> tools;
ChatRequest() {
}
ChatRequest(String model, List<Message> messages, Options options, Boolean stream, List<Tool> tools, String format) {
this.model = model;
this.messages = messages;
this.options = options;
this.stream = stream;
this.tools = tools;
this.format = format;
}
static Builder builder() {
return new Builder();
}
public String getModel() {
return model;
}
public void setModel(String model) {
this.model = model;
}
public List<Message> getMessages() {
return messages;
}
public void setMessages(List<Message> messages) {
this.messages = messages;
}
public Options getOptions() {
return options;
}
public void setOptions(Options options) {
this.options = options;
}
public String getFormat() {
return format;
}
public void setFormat(String format) {
this.format = format;
}
public Boolean getStream() {
return stream;
}
public void setStream(Boolean stream) {
this.stream = stream;
}
public List<Tool> getTools() {
return tools;
}
public void setTools(List<Tool> tools) {
this.tools = tools;
}
static class Builder {
private String model;
private List<Message> messages;
private Options options;
private String format;
private Boolean stream;
private List<Tool> tools;
Builder model(String model) {
this.model = model;
return this;
}
Builder messages(List<Message> messages) {
this.messages = messages;
return this;
}
Builder options(Options options) {
this.options = options;
return this;
}
Builder format(String format) {
this.format = format;
return this;
}
Builder stream(Boolean stream) {
this.stream = stream;
return this;
}
Builder tools(List<Tool> tools) {
this.tools = tools;
return this;
}
ChatRequest build() {
return new ChatRequest(model, messages, options, stream, tools, format);
}
}
}

View File

@ -4,17 +4,9 @@ import com.fasterxml.jackson.annotation.JsonIgnoreProperties;
import com.fasterxml.jackson.annotation.JsonInclude;
import com.fasterxml.jackson.databind.PropertyNamingStrategies.SnakeCaseStrategy;
import com.fasterxml.jackson.databind.annotation.JsonNaming;
import lombok.AllArgsConstructor;
import lombok.Builder;
import lombok.Data;
import lombok.NoArgsConstructor;
import static com.fasterxml.jackson.annotation.JsonInclude.Include.NON_NULL;
@Data
@NoArgsConstructor
@AllArgsConstructor
@Builder
@JsonIgnoreProperties(ignoreUnknown = true)
@JsonInclude(NON_NULL)
@JsonNaming(SnakeCaseStrategy.class)
@ -26,4 +18,113 @@ class ChatResponse {
private Boolean done;
private Integer promptEvalCount;
private Integer evalCount;
ChatResponse() {
}
ChatResponse(String model, String createdAt, Message message, Boolean done, Integer promptEvalCount, Integer evalCount) {
this.model = model;
this.createdAt = createdAt;
this.message = message;
this.done = done;
this.promptEvalCount = promptEvalCount;
this.evalCount = evalCount;
}
static Builder builder() {
return new Builder();
}
public String getModel() {
return model;
}
public void setModel(String model) {
this.model = model;
}
public String getCreatedAt() {
return createdAt;
}
public void setCreatedAt(String createdAt) {
this.createdAt = createdAt;
}
public Message getMessage() {
return message;
}
public void setMessage(Message message) {
this.message = message;
}
public Boolean getDone() {
return done;
}
public void setDone(Boolean done) {
this.done = done;
}
public Integer getPromptEvalCount() {
return promptEvalCount;
}
public void setPromptEvalCount(Integer promptEvalCount) {
this.promptEvalCount = promptEvalCount;
}
public Integer getEvalCount() {
return evalCount;
}
public void setEvalCount(Integer evalCount) {
this.evalCount = evalCount;
}
static class Builder {
private String model;
private String createdAt;
private Message message;
private Boolean done;
private Integer promptEvalCount;
private Integer evalCount;
Builder model(String model) {
this.model = model;
return this;
}
Builder createdAt(String createdAt) {
this.createdAt = createdAt;
return this;
}
Builder message(Message message) {
this.message = message;
return this;
}
Builder done(Boolean done) {
this.done = done;
return this;
}
Builder promptEvalCount(Integer promptEvalCount) {
this.promptEvalCount = promptEvalCount;
return this;
}
Builder evalCount(Integer evalCount) {
this.evalCount = evalCount;
return this;
}
ChatResponse build() {
return new ChatResponse(model, createdAt, message, done, promptEvalCount, evalCount);
}
}
}

View File

@ -4,17 +4,9 @@ import com.fasterxml.jackson.annotation.JsonIgnoreProperties;
import com.fasterxml.jackson.annotation.JsonInclude;
import com.fasterxml.jackson.databind.PropertyNamingStrategies.SnakeCaseStrategy;
import com.fasterxml.jackson.databind.annotation.JsonNaming;
import lombok.AllArgsConstructor;
import lombok.Builder;
import lombok.Data;
import lombok.NoArgsConstructor;
import static com.fasterxml.jackson.annotation.JsonInclude.Include.NON_NULL;
@Data
@NoArgsConstructor
@AllArgsConstructor
@Builder
@JsonIgnoreProperties(ignoreUnknown = true)
@JsonInclude(NON_NULL)
@JsonNaming(SnakeCaseStrategy.class)
@ -26,4 +18,112 @@ class CompletionRequest {
private Options options;
private String format;
private Boolean stream;
CompletionRequest() {
}
CompletionRequest(String model, String system, String prompt, Options options, String format, Boolean stream) {
this.model = model;
this.system = system;
this.prompt = prompt;
this.options = options;
this.format = format;
this.stream = stream;
}
static Builder builder() {
return new Builder();
}
public String getModel() {
return model;
}
public void setModel(String model) {
this.model = model;
}
public String getSystem() {
return system;
}
public void setSystem(String system) {
this.system = system;
}
public String getPrompt() {
return prompt;
}
public void setPrompt(String prompt) {
this.prompt = prompt;
}
public Options getOptions() {
return options;
}
public void setOptions(Options options) {
this.options = options;
}
public String getFormat() {
return format;
}
public void setFormat(String format) {
this.format = format;
}
public Boolean getStream() {
return stream;
}
public void setStream(Boolean stream) {
this.stream = stream;
}
static class Builder {
private String model;
private String system;
private String prompt;
private Options options;
private String format;
private Boolean stream;
Builder model(String model) {
this.model = model;
return this;
}
Builder system(String system) {
this.system = system;
return this;
}
Builder prompt(String prompt) {
this.prompt = prompt;
return this;
}
Builder options(Options options) {
this.options = options;
return this;
}
Builder format(String format) {
this.format = format;
return this;
}
Builder stream(Boolean stream) {
this.stream = stream;
return this;
}
CompletionRequest build() {
return new CompletionRequest(model, system, prompt, options, format, stream);
}
}
}

View File

@ -4,17 +4,9 @@ import com.fasterxml.jackson.annotation.JsonIgnoreProperties;
import com.fasterxml.jackson.annotation.JsonInclude;
import com.fasterxml.jackson.databind.PropertyNamingStrategies.SnakeCaseStrategy;
import com.fasterxml.jackson.databind.annotation.JsonNaming;
import lombok.AllArgsConstructor;
import lombok.Builder;
import lombok.Data;
import lombok.NoArgsConstructor;
import static com.fasterxml.jackson.annotation.JsonInclude.Include.NON_NULL;
@Data
@NoArgsConstructor
@AllArgsConstructor
@Builder
@JsonIgnoreProperties(ignoreUnknown = true)
@JsonInclude(NON_NULL)
@JsonNaming(SnakeCaseStrategy.class)
@ -26,4 +18,108 @@ class CompletionResponse {
private Boolean done;
private Integer promptEvalCount;
private Integer evalCount;
CompletionResponse() {
}
CompletionResponse(String model, String createdAt, String response, Boolean done, Integer promptEvalCount, Integer evalCount) {
this.model = model;
this.createdAt = createdAt;
this.response = response;
this.done = done;
this.promptEvalCount = promptEvalCount;
this.evalCount = evalCount;
}
public String getModel() {
return model;
}
public void setModel(String model) {
this.model = model;
}
public String getCreatedAt() {
return createdAt;
}
public void setCreatedAt(String createdAt) {
this.createdAt = createdAt;
}
public Boolean getDone() {
return done;
}
public void setDone(Boolean done) {
this.done = done;
}
public String getResponse() {
return response;
}
public void setResponse(String response) {
this.response = response;
}
public Integer getPromptEvalCount() {
return promptEvalCount;
}
public void setPromptEvalCount(Integer promptEvalCount) {
this.promptEvalCount = promptEvalCount;
}
public Integer getEvalCount() {
return evalCount;
}
public void setEvalCount(Integer evalCount) {
this.evalCount = evalCount;
}
static class Builder {
private String model;
private String createdAt;
private String response;
private Boolean done;
private Integer promptEvalCount;
private Integer evalCount;
Builder model(String model) {
this.model = model;
return this;
}
Builder createdAt(String createdAt) {
this.createdAt = createdAt;
return this;
}
Builder response(String response) {
this.response = response;
return this;
}
Builder done(Boolean done) {
this.done = done;
return this;
}
Builder promptEvalCount(Integer promptEvalCount) {
this.promptEvalCount = promptEvalCount;
return this;
}
Builder evalCount(Integer evalCount) {
this.evalCount = evalCount;
return this;
}
CompletionResponse build() {
return new CompletionResponse(model, createdAt, response, done, promptEvalCount, evalCount);
}
}
}

View File

@ -1,15 +1,49 @@
package dev.langchain4j.model.ollama;
import lombok.AllArgsConstructor;
import lombok.Builder;
import lombok.Data;
import lombok.NoArgsConstructor;
import com.fasterxml.jackson.annotation.JsonIgnoreProperties;
import com.fasterxml.jackson.annotation.JsonInclude;
import com.fasterxml.jackson.databind.PropertyNamingStrategies.SnakeCaseStrategy;
import com.fasterxml.jackson.databind.annotation.JsonNaming;
@Data
@NoArgsConstructor
@AllArgsConstructor
@Builder
import static com.fasterxml.jackson.annotation.JsonInclude.Include.NON_NULL;
@JsonIgnoreProperties(ignoreUnknown = true)
@JsonInclude(NON_NULL)
@JsonNaming(SnakeCaseStrategy.class)
class DeleteModelRequest {
private String name;
DeleteModelRequest() {
}
DeleteModelRequest(String name) {
this.name = name;
}
static Builder builder() {
return new Builder();
}
public String getName() {
return name;
}
public void setName(String name) {
this.name = name;
}
static class Builder {
private String name;
Builder name(String name) {
this.name = name;
return this;
}
DeleteModelRequest build() {
return new DeleteModelRequest(name);
}
}
}

View File

@ -4,19 +4,11 @@ import com.fasterxml.jackson.annotation.JsonIgnoreProperties;
import com.fasterxml.jackson.annotation.JsonInclude;
import com.fasterxml.jackson.databind.PropertyNamingStrategies.SnakeCaseStrategy;
import com.fasterxml.jackson.databind.annotation.JsonNaming;
import lombok.AllArgsConstructor;
import lombok.Builder;
import lombok.Data;
import lombok.NoArgsConstructor;
import java.util.List;
import static com.fasterxml.jackson.annotation.JsonInclude.Include.NON_NULL;
@Data
@NoArgsConstructor
@AllArgsConstructor
@Builder
@JsonIgnoreProperties(ignoreUnknown = true)
@JsonInclude(NON_NULL)
@JsonNaming(SnakeCaseStrategy.class)
@ -24,4 +16,52 @@ class EmbeddingRequest {
private String model;
private List<String> input;
EmbeddingRequest() {
}
EmbeddingRequest(String model, List<String> input) {
this.model = model;
this.input = input;
}
static Builder builder() {
return new Builder();
}
public String getModel() {
return model;
}
public void setModel(String model) {
this.model = model;
}
public List<String> getInput() {
return input;
}
public void setInput(List<String> input) {
this.input = input;
}
static class Builder {
private String model;
private List<String> input;
Builder model(String model) {
this.model = model;
return this;
}
Builder input(List<String> input) {
this.input = input;
return this;
}
EmbeddingRequest build() {
return new EmbeddingRequest(model, input);
}
}
}

View File

@ -4,19 +4,11 @@ import com.fasterxml.jackson.annotation.JsonIgnoreProperties;
import com.fasterxml.jackson.annotation.JsonInclude;
import com.fasterxml.jackson.databind.PropertyNamingStrategies.SnakeCaseStrategy;
import com.fasterxml.jackson.databind.annotation.JsonNaming;
import lombok.AllArgsConstructor;
import lombok.Builder;
import lombok.Data;
import lombok.NoArgsConstructor;
import java.util.List;
import static com.fasterxml.jackson.annotation.JsonInclude.Include.NON_NULL;
@Data
@NoArgsConstructor
@AllArgsConstructor
@Builder
@JsonIgnoreProperties(ignoreUnknown = true)
@JsonInclude(NON_NULL)
@JsonNaming(SnakeCaseStrategy.class)
@ -24,4 +16,52 @@ class EmbeddingResponse {
private String model;
private List<float[]> embeddings;
EmbeddingResponse() {
}
EmbeddingResponse(String model, List<float[]> embeddings) {
this.model = model;
this.embeddings = embeddings;
}
static Builder builder() {
return new Builder();
}
public String getModel() {
return model;
}
public void setModel(String model) {
this.model = model;
}
public List<float[]> getEmbeddings() {
return embeddings;
}
public void setEmbeddings(List<float[]> embeddings) {
this.embeddings = embeddings;
}
static class Builder {
private String model;
private List<float[]> embeddings;
Builder model(String model) {
this.model = model;
return this;
}
Builder embeddings(List<float[]> embeddings) {
this.embeddings = embeddings;
return this;
}
EmbeddingResponse build() {
return new EmbeddingResponse(model, embeddings);
}
}
}

View File

@ -2,24 +2,80 @@ package dev.langchain4j.model.ollama;
import com.fasterxml.jackson.annotation.JsonIgnoreProperties;
import com.fasterxml.jackson.annotation.JsonInclude;
import com.fasterxml.jackson.databind.PropertyNamingStrategies;
import com.fasterxml.jackson.databind.PropertyNamingStrategies.SnakeCaseStrategy;
import com.fasterxml.jackson.databind.annotation.JsonNaming;
import lombok.AllArgsConstructor;
import lombok.Builder;
import lombok.Data;
import lombok.NoArgsConstructor;
import static com.fasterxml.jackson.annotation.JsonInclude.Include.NON_NULL;
@Data
@NoArgsConstructor
@AllArgsConstructor
@Builder
@JsonIgnoreProperties(ignoreUnknown = true)
@JsonInclude(NON_NULL)
@JsonNaming(PropertyNamingStrategies.SnakeCaseStrategy.class)
@JsonNaming(SnakeCaseStrategy.class)
class Function {
private String name;
private String description;
private Parameters parameters;
Function() {
}
Function(String name, String description, Parameters parameters) {
this.name = name;
this.description = description;
this.parameters = parameters;
}
static Builder builder() {
return new Builder();
}
public String getName() {
return name;
}
public void setName(String name) {
this.name = name;
}
public String getDescription() {
return description;
}
public void setDescription(String description) {
this.description = description;
}
public Parameters getParameters() {
return parameters;
}
public void setParameters(Parameters parameters) {
this.parameters = parameters;
}
static class Builder {
private String name;
private String description;
private Parameters parameters;
Builder name(String name) {
this.name = name;
return this;
}
Builder description(String description) {
this.description = description;
return this;
}
Builder parameters(Parameters parameters) {
this.parameters = parameters;
return this;
}
Function build() {
return new Function(name, description, parameters);
}
}
}

View File

@ -4,23 +4,64 @@ import com.fasterxml.jackson.annotation.JsonIgnoreProperties;
import com.fasterxml.jackson.annotation.JsonInclude;
import com.fasterxml.jackson.databind.PropertyNamingStrategies;
import com.fasterxml.jackson.databind.annotation.JsonNaming;
import lombok.AllArgsConstructor;
import lombok.Builder;
import lombok.Data;
import lombok.NoArgsConstructor;
import java.util.Map;
import static com.fasterxml.jackson.annotation.JsonInclude.Include.NON_NULL;
@Data
@NoArgsConstructor
@AllArgsConstructor
@Builder
@JsonIgnoreProperties(ignoreUnknown = true)
@JsonInclude(NON_NULL)
@JsonNaming(PropertyNamingStrategies.SnakeCaseStrategy.class)
class FunctionCall {
private String name;
private Map<String, Object> arguments;
FunctionCall() {
}
FunctionCall(String name, Map<String, Object> arguments) {
this.name = name;
this.arguments = arguments;
}
static Builder builder() {
return new Builder();
}
public String getName() {
return name;
}
public void setName(String name) {
this.name = name;
}
public Map<String, Object> getArguments() {
return arguments;
}
public void setArguments(Map<String, Object> arguments) {
this.arguments = arguments;
}
static class Builder {
private String name;
private Map<String, Object> arguments;
Builder name(String name) {
this.name = name;
return this;
}
Builder arguments(Map<String, Object> arguments) {
this.arguments = arguments;
return this;
}
FunctionCall build() {
return new FunctionCall(name, arguments);
}
}
}

View File

@ -4,19 +4,11 @@ import com.fasterxml.jackson.annotation.JsonIgnoreProperties;
import com.fasterxml.jackson.annotation.JsonInclude;
import com.fasterxml.jackson.databind.PropertyNamingStrategies.SnakeCaseStrategy;
import com.fasterxml.jackson.databind.annotation.JsonNaming;
import lombok.AllArgsConstructor;
import lombok.Builder;
import lombok.Data;
import lombok.NoArgsConstructor;
import java.util.List;
import static com.fasterxml.jackson.annotation.JsonInclude.Include.NON_NULL;
@Data
@NoArgsConstructor
@AllArgsConstructor
@Builder
@JsonIgnoreProperties(ignoreUnknown = true)
@JsonInclude(NON_NULL)
@JsonNaming(SnakeCaseStrategy.class)
@ -26,4 +18,82 @@ class Message {
private String content;
private List<String> images;
private List<ToolCall> toolCalls;
Message() {
}
public Message(Role role, String content, List<String> images, List<ToolCall> toolCalls) {
this.role = role;
this.content = content;
this.images = images;
this.toolCalls = toolCalls;
}
static Builder builder() {
return new Builder();
}
public Role getRole() {
return role;
}
public void setRole(Role role) {
this.role = role;
}
public String getContent() {
return content;
}
public void setContent(String content) {
this.content = content;
}
public List<String> getImages() {
return images;
}
public void setImages(List<String> images) {
this.images = images;
}
public List<ToolCall> getToolCalls() {
return toolCalls;
}
public void setToolCalls(List<ToolCall> toolCalls) {
this.toolCalls = toolCalls;
}
static class Builder {
private Role role;
private String content;
private List<String> images;
private List<ToolCall> toolCalls;
Builder role(Role role) {
this.role = role;
return this;
}
Builder content(String content) {
this.content = content;
return this;
}
Builder images(List<String> images) {
this.images = images;
return this;
}
Builder toolCalls(List<ToolCall> toolCalls) {
this.toolCalls = toolCalls;
return this;
}
Message build() {
return new Message(role, content, images, toolCalls);
}
}
}

View File

@ -4,23 +4,48 @@ import com.fasterxml.jackson.annotation.JsonIgnoreProperties;
import com.fasterxml.jackson.annotation.JsonInclude;
import com.fasterxml.jackson.databind.PropertyNamingStrategies.SnakeCaseStrategy;
import com.fasterxml.jackson.databind.annotation.JsonNaming;
import lombok.AllArgsConstructor;
import lombok.Builder;
import lombok.Data;
import lombok.NoArgsConstructor;
import java.util.List;
import static com.fasterxml.jackson.annotation.JsonInclude.Include.NON_NULL;
@Data
@NoArgsConstructor
@AllArgsConstructor
@Builder
@JsonIgnoreProperties(ignoreUnknown = true)
@JsonInclude(NON_NULL)
@JsonNaming(SnakeCaseStrategy.class)
class ModelsListResponse {
private List<OllamaModel> models;
ModelsListResponse() {
}
ModelsListResponse(List<OllamaModel> models) {
this.models = models;
}
static Builder builder() {
return new Builder();
}
public List<OllamaModel> getModels() {
return models;
}
public void setModels(List<OllamaModel> models) {
this.models = models;
}
static class Builder {
private List<OllamaModel> models;
Builder models(List<OllamaModel> models) {
this.models = models;
return this;
}
ModelsListResponse build() {
return new ModelsListResponse(models);
}
}
}

View File

@ -40,7 +40,7 @@ interface OllamaApi {
@Headers({"Content-Type: application/json"})
Call<Void> deleteModel(@Body DeleteModelRequest deleteModelRequest);
@GET( "api/ps")
@GET("api/ps")
@Headers({"Content-Type: application/json"})
Call<RunningModelsListResponse> listRunningModels();
}

View File

@ -7,7 +7,6 @@ import dev.langchain4j.model.chat.ChatLanguageModel;
import dev.langchain4j.model.ollama.spi.OllamaChatModelBuilderFactory;
import dev.langchain4j.model.output.Response;
import dev.langchain4j.model.output.TokenUsage;
import lombok.Builder;
import java.time.Duration;
import java.util.List;
@ -34,7 +33,6 @@ public class OllamaChatModel implements ChatLanguageModel {
private final String format;
private final Integer maxRetries;
@Builder
public OllamaChatModel(String baseUrl,
String modelName,
Double temperature,
@ -73,6 +71,13 @@ public class OllamaChatModel implements ChatLanguageModel {
this.maxRetries = getOrDefault(maxRetries, 3);
}
public static OllamaChatModelBuilder builder() {
for (OllamaChatModelBuilderFactory factory : loadFactories(OllamaChatModelBuilderFactory.class)) {
return factory.get();
}
return new OllamaChatModelBuilder();
}
@Override
public Response<AiMessage> generate(List<ChatMessage> messages) {
ensureNotEmpty(messages, "messages");
@ -116,18 +121,130 @@ public class OllamaChatModel implements ChatLanguageModel {
);
}
public static OllamaChatModelBuilder builder() {
for (OllamaChatModelBuilderFactory factory : loadFactories(OllamaChatModelBuilderFactory.class)) {
return factory.get();
}
return new OllamaChatModelBuilder();
}
public static class OllamaChatModelBuilder {
private String baseUrl;
private String modelName;
private Double temperature;
private Integer topK;
private Double topP;
private Double repeatPenalty;
private Integer seed;
private Integer numPredict;
private Integer numCtx;
private List<String> stop;
private String format;
private Duration timeout;
private Integer maxRetries;
private Map<String, String> customHeaders;
private Boolean logRequests;
private Boolean logResponses;
public OllamaChatModelBuilder() {
// This is public so it can be extended
// By default with Lombok it becomes package private
}
public OllamaChatModelBuilder baseUrl(String baseUrl) {
this.baseUrl = baseUrl;
return this;
}
public OllamaChatModelBuilder modelName(String modelName) {
this.modelName = modelName;
return this;
}
public OllamaChatModelBuilder temperature(Double temperature) {
this.temperature = temperature;
return this;
}
public OllamaChatModelBuilder topK(Integer topK) {
this.topK = topK;
return this;
}
public OllamaChatModelBuilder topP(Double topP) {
this.topP = topP;
return this;
}
public OllamaChatModelBuilder repeatPenalty(Double repeatPenalty) {
this.repeatPenalty = repeatPenalty;
return this;
}
public OllamaChatModelBuilder seed(Integer seed) {
this.seed = seed;
return this;
}
public OllamaChatModelBuilder numPredict(Integer numPredict) {
this.numPredict = numPredict;
return this;
}
public OllamaChatModelBuilder numCtx(Integer numCtx) {
this.numCtx = numCtx;
return this;
}
public OllamaChatModelBuilder stop(List<String> stop) {
this.stop = stop;
return this;
}
public OllamaChatModelBuilder format(String format) {
this.format = format;
return this;
}
public OllamaChatModelBuilder timeout(Duration timeout) {
this.timeout = timeout;
return this;
}
public OllamaChatModelBuilder maxRetries(Integer maxRetries) {
this.maxRetries = maxRetries;
return this;
}
public OllamaChatModelBuilder customHeaders(Map<String, String> customHeaders) {
this.customHeaders = customHeaders;
return this;
}
public OllamaChatModelBuilder logRequests(Boolean logRequests) {
this.logRequests = logRequests;
return this;
}
public OllamaChatModelBuilder logResponses(Boolean logResponses) {
this.logResponses = logResponses;
return this;
}
public OllamaChatModel build() {
return new OllamaChatModel(
baseUrl,
modelName,
temperature,
topK,
topP,
repeatPenalty,
seed,
numPredict,
numCtx,
stop,
format,
timeout,
maxRetries,
customHeaders,
logRequests,
logResponses
);
}
}
}

View File

@ -5,13 +5,13 @@ import dev.langchain4j.internal.Utils;
import dev.langchain4j.model.StreamingResponseHandler;
import dev.langchain4j.model.output.Response;
import dev.langchain4j.model.output.TokenUsage;
import lombok.Builder;
import lombok.extern.slf4j.Slf4j;
import okhttp3.Interceptor;
import okhttp3.OkHttpClient;
import okhttp3.Request;
import okhttp3.ResponseBody;
import org.jetbrains.annotations.NotNull;
import org.slf4j.Logger;
import org.slf4j.LoggerFactory;
import retrofit2.Call;
import retrofit2.Callback;
import retrofit2.Retrofit;
@ -30,13 +30,13 @@ import static dev.langchain4j.model.ollama.OllamaJsonUtils.getObjectMapper;
import static dev.langchain4j.model.ollama.OllamaJsonUtils.toObject;
import static java.lang.Boolean.TRUE;
@Slf4j
class OllamaClient {
private static final Logger log = LoggerFactory.getLogger(OllamaClient.class);
private final OllamaApi ollamaApi;
private final boolean logStreamingResponses;
@Builder
public OllamaClient(String baseUrl,
Duration timeout,
Boolean logRequests, Boolean logResponses, Boolean logStreamingResponses,
@ -69,6 +69,10 @@ class OllamaClient {
ollamaApi = retrofit.create(OllamaApi.class);
}
static Builder builder() {
return new Builder();
}
public CompletionResponse completion(CompletionRequest request) {
try {
retrofit2.Response<CompletionResponse> retrofitResponse
@ -281,4 +285,48 @@ class OllamaClient {
return chain.proceed(builder.build());
}
}
static class Builder {
private String baseUrl;
private Duration timeout;
private Boolean logRequests;
private Boolean logResponses;
private Boolean logStreamingResponses;
private Map<String, String> customHeaders;
Builder baseUrl(String baseUrl) {
this.baseUrl = baseUrl;
return this;
}
Builder timeout(Duration timeout) {
this.timeout = timeout;
return this;
}
Builder logRequests(Boolean logRequests) {
this.logRequests = logRequests;
return this;
}
Builder logResponses(Boolean logResponses) {
this.logResponses = logResponses;
return this;
}
Builder logStreamingResponses(Boolean logStreamingResponses) {
this.logStreamingResponses = logStreamingResponses;
return this;
}
Builder customHeaders(Map<String, String> customHeaders) {
this.customHeaders = customHeaders;
return this;
}
OllamaClient build() {
return new OllamaClient(baseUrl, timeout, logRequests, logResponses, logStreamingResponses, customHeaders);
}
}
}

View File

@ -19,7 +19,7 @@ class OllamaDateDeserializer extends JsonDeserializer<OffsetDateTime> {
String date = p.getText();
if (date.contains(".")) {
String[] parts = date.split("\\.");
if(parts[1].contains("+")) {
if (parts[1].contains("+")) {
String nanoseconds = parts[1].substring(0, parts[1].indexOf('+'));
date = date.replaceAll(nanoseconds, "");
} else {

View File

@ -5,7 +5,6 @@ import dev.langchain4j.data.segment.TextSegment;
import dev.langchain4j.model.embedding.DimensionAwareEmbeddingModel;
import dev.langchain4j.model.ollama.spi.OllamaEmbeddingModelBuilderFactory;
import dev.langchain4j.model.output.Response;
import lombok.Builder;
import java.time.Duration;
import java.util.List;
@ -27,7 +26,6 @@ public class OllamaEmbeddingModel extends DimensionAwareEmbeddingModel {
private final String modelName;
private final Integer maxRetries;
@Builder
public OllamaEmbeddingModel(String baseUrl,
String modelName,
Duration timeout,
@ -46,6 +44,13 @@ public class OllamaEmbeddingModel extends DimensionAwareEmbeddingModel {
this.maxRetries = getOrDefault(maxRetries, 3);
}
public static OllamaEmbeddingModelBuilder builder() {
for (OllamaEmbeddingModelBuilderFactory factory : loadFactories(OllamaEmbeddingModelBuilderFactory.class)) {
return factory.get();
}
return new OllamaEmbeddingModelBuilder();
}
@Override
public Response<List<Embedding>> embedAll(List<TextSegment> textSegments) {
List<String> input = textSegments.stream()
@ -65,17 +70,58 @@ public class OllamaEmbeddingModel extends DimensionAwareEmbeddingModel {
return Response.from(embeddings);
}
public static OllamaEmbeddingModelBuilder builder() {
for (OllamaEmbeddingModelBuilderFactory factory : loadFactories(OllamaEmbeddingModelBuilderFactory.class)) {
return factory.get();
}
return new OllamaEmbeddingModelBuilder();
}
public static class OllamaEmbeddingModelBuilder {
private String baseUrl;
private String modelName;
private Duration timeout;
private Integer maxRetries;
private Boolean logRequests;
private Boolean logResponses;
private Map<String, String> customHeaders;
public OllamaEmbeddingModelBuilder() {
// This is public so it can be extended
// By default with Lombok it becomes package private
}
public OllamaEmbeddingModelBuilder baseUrl(String baseUrl) {
this.baseUrl = baseUrl;
return this;
}
public OllamaEmbeddingModelBuilder modelName(String modelName) {
this.modelName = modelName;
return this;
}
public OllamaEmbeddingModelBuilder timeout(Duration timeout) {
this.timeout = timeout;
return this;
}
public OllamaEmbeddingModelBuilder maxRetries(Integer maxRetries) {
this.maxRetries = maxRetries;
return this;
}
public OllamaEmbeddingModelBuilder logRequests(Boolean logRequests) {
this.logRequests = logRequests;
return this;
}
public OllamaEmbeddingModelBuilder logResponses(Boolean logResponses) {
this.logResponses = logResponses;
return this;
}
public OllamaEmbeddingModelBuilder customHeaders(Map<String, String> customHeaders) {
this.customHeaders = customHeaders;
return this;
}
public OllamaEmbeddingModel build() {
return new OllamaEmbeddingModel(baseUrl, modelName, timeout, maxRetries, logRequests, logResponses, customHeaders);
}
}
}

View File

@ -4,7 +4,6 @@ import dev.langchain4j.model.language.LanguageModel;
import dev.langchain4j.model.ollama.spi.OllamaLanguageModelBuilderFactory;
import dev.langchain4j.model.output.Response;
import dev.langchain4j.model.output.TokenUsage;
import lombok.Builder;
import java.time.Duration;
import java.util.List;
@ -29,7 +28,6 @@ public class OllamaLanguageModel implements LanguageModel {
private final String format;
private final Integer maxRetries;
@Builder
public OllamaLanguageModel(String baseUrl,
String modelName,
Double temperature,
@ -46,7 +44,7 @@ public class OllamaLanguageModel implements LanguageModel {
Boolean logRequests,
Boolean logResponses,
Map<String, String> customHeaders
) {
) {
this.client = OllamaClient.builder()
.baseUrl(baseUrl)
.timeout(getOrDefault(timeout, ofSeconds(60)))
@ -69,6 +67,13 @@ public class OllamaLanguageModel implements LanguageModel {
this.maxRetries = getOrDefault(maxRetries, 3);
}
public static OllamaLanguageModelBuilder builder() {
for (OllamaLanguageModelBuilderFactory factory : loadFactories(OllamaLanguageModelBuilderFactory.class)) {
return factory.get();
}
return new OllamaLanguageModelBuilder();
}
@Override
public Response<String> generate(String prompt) {
@ -88,17 +93,129 @@ public class OllamaLanguageModel implements LanguageModel {
);
}
public static OllamaLanguageModelBuilder builder() {
for (OllamaLanguageModelBuilderFactory factory : loadFactories(OllamaLanguageModelBuilderFactory.class)) {
return factory.get();
}
return new OllamaLanguageModelBuilder();
}
public static class OllamaLanguageModelBuilder {
private String baseUrl;
private String modelName;
private Double temperature;
private Integer topK;
private Double topP;
private Double repeatPenalty;
private Integer seed;
private Integer numPredict;
private Integer numCtx;
private List<String> stop;
private String format;
private Duration timeout;
private Integer maxRetries;
private Boolean logRequests;
private Boolean logResponses;
private Map<String, String> customHeaders;
public OllamaLanguageModelBuilder() {
// This is public so it can be extended
// By default with Lombok it becomes package private
}
public OllamaLanguageModelBuilder baseUrl(String baseUrl) {
this.baseUrl = baseUrl;
return this;
}
public OllamaLanguageModelBuilder modelName(String modelName) {
this.modelName = modelName;
return this;
}
public OllamaLanguageModelBuilder temperature(Double temperature) {
this.temperature = temperature;
return this;
}
public OllamaLanguageModelBuilder topK(Integer topK) {
this.topK = topK;
return this;
}
public OllamaLanguageModelBuilder topP(Double topP) {
this.topP = topP;
return this;
}
public OllamaLanguageModelBuilder repeatPenalty(Double repeatPenalty) {
this.repeatPenalty = repeatPenalty;
return this;
}
public OllamaLanguageModelBuilder seed(Integer seed) {
this.seed = seed;
return this;
}
public OllamaLanguageModelBuilder numPredict(Integer numPredict) {
this.numPredict = numPredict;
return this;
}
public OllamaLanguageModelBuilder numCtx(Integer numCtx) {
this.numCtx = numCtx;
return this;
}
public OllamaLanguageModelBuilder stop(List<String> stop) {
this.stop = stop;
return this;
}
public OllamaLanguageModelBuilder format(String format) {
this.format = format;
return this;
}
public OllamaLanguageModelBuilder timeout(Duration timeout) {
this.timeout = timeout;
return this;
}
public OllamaLanguageModelBuilder maxRetries(Integer maxRetries) {
this.maxRetries = maxRetries;
return this;
}
public OllamaLanguageModelBuilder logRequests(Boolean logRequests) {
this.logRequests = logRequests;
return this;
}
public OllamaLanguageModelBuilder logResponses(Boolean logResponses) {
this.logResponses = logResponses;
return this;
}
public OllamaLanguageModelBuilder customHeaders(Map<String, String> customHeaders) {
this.customHeaders = customHeaders;
return this;
}
public OllamaLanguageModel build() {
return new OllamaLanguageModel(
baseUrl,
modelName,
temperature,
topK,
topP,
repeatPenalty,
seed,
numPredict,
numCtx,
stop,
format,
timeout,
maxRetries,
logRequests,
logResponses,
customHeaders
);
}
}
}

View File

@ -5,19 +5,11 @@ import com.fasterxml.jackson.annotation.JsonInclude;
import com.fasterxml.jackson.databind.PropertyNamingStrategies.SnakeCaseStrategy;
import com.fasterxml.jackson.databind.annotation.JsonDeserialize;
import com.fasterxml.jackson.databind.annotation.JsonNaming;
import lombok.AllArgsConstructor;
import lombok.Builder;
import lombok.Data;
import lombok.NoArgsConstructor;
import java.time.OffsetDateTime;
import static com.fasterxml.jackson.annotation.JsonInclude.Include.NON_NULL;
@Data
@NoArgsConstructor
@AllArgsConstructor
@Builder
@JsonIgnoreProperties(ignoreUnknown = true)
@JsonInclude(NON_NULL)
@JsonNaming(SnakeCaseStrategy.class)
@ -30,4 +22,82 @@ public class OllamaModel {
private long size;
private String digest;
private OllamaModelDetails details;
OllamaModel() {
}
OllamaModel(String name, long size, String digest, OllamaModelDetails details) {
this.name = name;
this.size = size;
this.digest = digest;
this.details = details;
}
static Builder builder() {
return new Builder();
}
public String getName() {
return name;
}
public void setName(String name) {
this.name = name;
}
public long getSize() {
return size;
}
public void setSize(long size) {
this.size = size;
}
public String getDigest() {
return digest;
}
public void setDigest(String digest) {
this.digest = digest;
}
public OllamaModelDetails getDetails() {
return details;
}
public void setDetails(OllamaModelDetails details) {
this.details = details;
}
static class Builder {
private String name;
private long size;
private String digest;
private OllamaModelDetails details;
Builder name(String name) {
this.name = name;
return this;
}
Builder size(long size) {
this.size = size;
return this;
}
Builder digest(String digest) {
this.digest = digest;
return this;
}
Builder details(OllamaModelDetails details) {
this.details = details;
return this;
}
OllamaModel build() {
return new OllamaModel(name, size, digest, details);
}
}
}

View File

@ -5,20 +5,12 @@ import com.fasterxml.jackson.annotation.JsonInclude;
import com.fasterxml.jackson.databind.PropertyNamingStrategies.SnakeCaseStrategy;
import com.fasterxml.jackson.databind.annotation.JsonDeserialize;
import com.fasterxml.jackson.databind.annotation.JsonNaming;
import lombok.AllArgsConstructor;
import lombok.Builder;
import lombok.Data;
import lombok.NoArgsConstructor;
import java.time.OffsetDateTime;
import java.util.Map;
import static com.fasterxml.jackson.annotation.JsonInclude.Include.NON_NULL;
@Data
@NoArgsConstructor
@AllArgsConstructor
@Builder
@JsonIgnoreProperties(ignoreUnknown = true)
@JsonInclude(NON_NULL)
@JsonNaming(SnakeCaseStrategy.class)
@ -29,7 +21,127 @@ public class OllamaModelCard {
private String parameters;
private String template;
private OllamaModelDetails details;
private Map<String,Object> modelInfo;
private Map<String, Object> modelInfo;
@JsonDeserialize(using = OllamaDateDeserializer.class)
private OffsetDateTime modifiedAt;
OllamaModelCard() {
}
OllamaModelCard(String modelfile, String parameters, String template, OllamaModelDetails details) {
this.modelfile = modelfile;
this.parameters = parameters;
this.template = template;
this.details = details;
}
static Builder builder() {
return new Builder();
}
public String getLicense() {
return license;
}
public void setLicense(String license) {
this.license = license;
}
public String getModelfile() {
return modelfile;
}
public void setModelfile(String modelfile) {
this.modelfile = modelfile;
}
public String getParameters() {
return parameters;
}
public void setParameters(String parameters) {
this.parameters = parameters;
}
public String getTemplate() {
return template;
}
public void setTemplate(String template) {
this.template = template;
}
public OllamaModelDetails getDetails() {
return details;
}
public void setDetails(OllamaModelDetails details) {
this.details = details;
}
public Map<String, Object> getModelInfo() {
return modelInfo;
}
public void setModelInfo(Map<String, Object> modelInfo) {
this.modelInfo = modelInfo;
}
public OffsetDateTime getModifiedAt() {
return modifiedAt;
}
public void setModifiedAt(OffsetDateTime modifiedAt) {
this.modifiedAt = modifiedAt;
}
static class Builder {
private String license;
private String modelfile;
private String parameters;
private String template;
private OllamaModelDetails details;
private Map<String, Object> modelInfo;
private OffsetDateTime modifiedAt;
Builder license(String license) {
this.license = license;
return this;
}
Builder modelfile(String modelfile) {
this.modelfile = modelfile;
return this;
}
Builder parameters(String parameters) {
this.parameters = parameters;
return this;
}
Builder template(String template) {
this.template = template;
return this;
}
Builder details(OllamaModelDetails details) {
this.details = details;
return this;
}
Builder modelInfo(Map<String, Object> modelInfo) {
this.modelInfo = modelInfo;
return this;
}
Builder modifiedAt(OffsetDateTime modifiedAt) {
this.modifiedAt = modifiedAt;
return this;
}
OllamaModelCard build() {
return new OllamaModelCard(modelfile, parameters, template, details);
}
}
}

View File

@ -4,19 +4,11 @@ import com.fasterxml.jackson.annotation.JsonIgnoreProperties;
import com.fasterxml.jackson.annotation.JsonInclude;
import com.fasterxml.jackson.databind.PropertyNamingStrategies.SnakeCaseStrategy;
import com.fasterxml.jackson.databind.annotation.JsonNaming;
import lombok.AllArgsConstructor;
import lombok.Builder;
import lombok.Data;
import lombok.NoArgsConstructor;
import java.util.List;
import static com.fasterxml.jackson.annotation.JsonInclude.Include.NON_NULL;
@Data
@NoArgsConstructor
@AllArgsConstructor
@Builder
@JsonIgnoreProperties(ignoreUnknown = true)
@JsonInclude(NON_NULL)
@JsonNaming(SnakeCaseStrategy.class)
@ -27,4 +19,97 @@ public class OllamaModelDetails {
private List<String> families;
private String parameterSize;
private String quantizationLevel;
OllamaModelDetails() {
}
OllamaModelDetails(String format, String family, List<String> families, String parameterSize, String quantizationLevel) {
this.format = format;
this.family = family;
this.families = families;
this.parameterSize = parameterSize;
this.quantizationLevel = quantizationLevel;
}
static Builder builder() {
return new Builder();
}
public String getFormat() {
return format;
}
public void setFormat(String format) {
this.format = format;
}
public String getFamily() {
return family;
}
public void setFamily(String family) {
this.family = family;
}
public List<String> getFamilies() {
return families;
}
public void setFamilies(List<String> families) {
this.families = families;
}
public String getParameterSize() {
return parameterSize;
}
public void setParameterSize(String parameterSize) {
this.parameterSize = parameterSize;
}
public String getQuantizationLevel() {
return quantizationLevel;
}
public void setQuantizationLevel(String quantizationLevel) {
this.quantizationLevel = quantizationLevel;
}
static class Builder {
private String format;
private String family;
private List<String> families;
private String parameterSize;
private String quantizationLevel;
Builder format(String format) {
this.format = format;
return this;
}
Builder family(String family) {
this.family = family;
return this;
}
Builder families(List<String> families) {
this.families = families;
return this;
}
Builder parameterSize(String parameterSize) {
this.parameterSize = parameterSize;
return this;
}
Builder quantizationLevel(String quantizationLevel) {
this.quantizationLevel = quantizationLevel;
return this;
}
OllamaModelDetails build() {
return new OllamaModelDetails(format, family, families, parameterSize, quantizationLevel);
}
}
}

View File

@ -1,7 +1,6 @@
package dev.langchain4j.model.ollama;
import dev.langchain4j.model.output.Response;
import lombok.Builder;
import java.time.Duration;
import java.util.List;
@ -14,13 +13,11 @@ public class OllamaModels {
private final OllamaClient client;
private final Integer maxRetries;
@Builder
public OllamaModels(String baseUrl,
Duration timeout,
Integer maxRetries,
Boolean logRequests,
Boolean logResponses
) {
Boolean logResponses) {
this.client = OllamaClient.builder()
.baseUrl(baseUrl)
.timeout((getOrDefault(timeout, Duration.ofSeconds(60))))
@ -30,6 +27,10 @@ public class OllamaModels {
this.maxRetries = getOrDefault(maxRetries, 3);
}
public static OllamaModelsBuilder builder() {
return new OllamaModelsBuilder();
}
public Response<List<OllamaModel>> availableModels() {
ModelsListResponse response = withRetry(client::listModels, maxRetries);
return Response.from(response.getModels());
@ -64,4 +65,42 @@ public class OllamaModels {
RunningModelsListResponse response = withRetry(client::listRunningModels, maxRetries);
return Response.from(response.getModels());
}
public static class OllamaModelsBuilder {
private String baseUrl;
private Duration timeout;
private Integer maxRetries;
private Boolean logRequests;
private Boolean logResponses;
OllamaModelsBuilder baseUrl(String baseUrl) {
this.baseUrl = baseUrl;
return this;
}
OllamaModelsBuilder timeout(Duration timeout) {
this.timeout = timeout;
return this;
}
OllamaModelsBuilder maxRetries(Integer maxRetries) {
this.maxRetries = maxRetries;
return this;
}
OllamaModelsBuilder logRequests(Boolean logRequests) {
this.logRequests = logRequests;
return this;
}
OllamaModelsBuilder logResponses(Boolean logResponses) {
this.logResponses = logResponses;
return this;
}
public OllamaModels build() {
return new OllamaModels(baseUrl, timeout, maxRetries, logRequests, logResponses);
}
}
}

View File

@ -1,11 +1,12 @@
package dev.langchain4j.model.ollama;
import lombok.extern.slf4j.Slf4j;
import okhttp3.Headers;
import okhttp3.Interceptor;
import okhttp3.Request;
import okhttp3.Response;
import okio.Buffer;
import org.slf4j.Logger;
import org.slf4j.LoggerFactory;
import java.io.IOException;
import java.util.HashSet;
@ -16,28 +17,13 @@ import static dev.langchain4j.internal.Utils.isNullOrBlank;
import static java.util.Arrays.asList;
import static java.util.stream.Collectors.joining;
@Slf4j
class OllamaRequestLoggingInterceptor implements Interceptor {
private static final Logger log = LoggerFactory.getLogger(OllamaRequestLoggingInterceptor.class);
private static final Set<String> COMMON_SECRET_HEADERS =
new HashSet<>(asList("authorization", "x-api-key", "x-auth-token"));
@Override
public Response intercept(Chain chain) throws IOException {
Request request = chain.request();
this.log(request);
return chain.proceed(request);
}
private void log(Request request) {
try {
log.debug("Request:\n- method: {}\n- url: {}\n- headers: {}\n- body: {}",
request.method(), request.url(), getHeaders(request.headers()), getBody(request));
} catch (Exception e) {
log.warn("Error while logging request: {}", e.getMessage());
}
}
private static String getBody(Request request) {
try {
Buffer buffer = new Buffer();
@ -76,4 +62,20 @@ class OllamaRequestLoggingInterceptor implements Interceptor {
return "..."; // to short to be masked
}
}
@Override
public Response intercept(Chain chain) throws IOException {
Request request = chain.request();
this.log(request);
return chain.proceed(request);
}
private void log(Request request) {
try {
log.debug("Request:\n- method: {}\n- url: {}\n- headers: {}\n- body: {}",
request.method(), request.url(), getHeaders(request.headers()), getBody(request));
} catch (Exception e) {
log.warn("Error while logging request: {}", e.getMessage());
}
}
}

View File

@ -1,15 +1,22 @@
package dev.langchain4j.model.ollama;
import lombok.extern.slf4j.Slf4j;
import okhttp3.Interceptor;
import okhttp3.Request;
import okhttp3.Response;
import org.slf4j.Logger;
import org.slf4j.LoggerFactory;
import java.io.IOException;
@Slf4j
class OllamaResponseLoggingInterceptor implements Interceptor {
private static final Logger log = LoggerFactory.getLogger(OllamaResponseLoggingInterceptor.class);
private static boolean isEventStream(Response response) {
String contentType = response.header("Content-Type");
return contentType != null && contentType.contains("event-stream");
}
@Override
public Response intercept(Chain chain) throws IOException {
Request request = chain.request();
@ -32,9 +39,4 @@ class OllamaResponseLoggingInterceptor implements Interceptor {
? "[skipping response body due to streaming]"
: response.peekBody(Long.MAX_VALUE).string();
}
private static boolean isEventStream(Response response) {
String contentType = response.header("Content-Type");
return contentType != null && contentType.contains("event-stream");
}
}

View File

@ -5,7 +5,6 @@ import dev.langchain4j.data.message.ChatMessage;
import dev.langchain4j.model.StreamingResponseHandler;
import dev.langchain4j.model.chat.StreamingChatLanguageModel;
import dev.langchain4j.model.ollama.spi.OllamaStreamingChatModelBuilderFactory;
import lombok.Builder;
import java.time.Duration;
import java.util.List;
@ -30,7 +29,6 @@ public class OllamaStreamingChatModel implements StreamingChatLanguageModel {
private final Options options;
private final String format;
@Builder
public OllamaStreamingChatModel(String baseUrl,
String modelName,
Double temperature,
@ -46,7 +44,7 @@ public class OllamaStreamingChatModel implements StreamingChatLanguageModel {
Boolean logRequests,
Boolean logResponses,
Map<String, String> customHeaders
) {
) {
this.client = OllamaClient.builder()
.baseUrl(baseUrl)
.timeout(getOrDefault(timeout, ofSeconds(60)))
@ -68,6 +66,13 @@ public class OllamaStreamingChatModel implements StreamingChatLanguageModel {
this.format = format;
}
public static OllamaStreamingChatModelBuilder builder() {
for (OllamaStreamingChatModelBuilderFactory factory : loadFactories(OllamaStreamingChatModelBuilderFactory.class)) {
return factory.get();
}
return new OllamaStreamingChatModelBuilder();
}
@Override
public void generate(List<ChatMessage> messages, StreamingResponseHandler<AiMessage> handler) {
ensureNotEmpty(messages, "messages");
@ -83,17 +88,122 @@ public class OllamaStreamingChatModel implements StreamingChatLanguageModel {
client.streamingChat(request, handler);
}
public static OllamaStreamingChatModelBuilder builder() {
for (OllamaStreamingChatModelBuilderFactory factory : loadFactories(OllamaStreamingChatModelBuilderFactory.class)) {
return factory.get();
}
return new OllamaStreamingChatModelBuilder();
}
public static class OllamaStreamingChatModelBuilder {
private String baseUrl;
private String modelName;
private Double temperature;
private Integer topK;
private Double topP;
private Double repeatPenalty;
private Integer seed;
private Integer numPredict;
private Integer numCtx;
private List<String> stop;
private String format;
private Duration timeout;
private Map<String, String> customHeaders;
private Boolean logRequests;
private Boolean logResponses;
public OllamaStreamingChatModelBuilder() {
// This is public so it can be extended
// By default with Lombok it becomes package private
}
public OllamaStreamingChatModelBuilder baseUrl(String baseUrl) {
this.baseUrl = baseUrl;
return this;
}
public OllamaStreamingChatModelBuilder modelName(String modelName) {
this.modelName = modelName;
return this;
}
public OllamaStreamingChatModelBuilder temperature(Double temperature) {
this.temperature = temperature;
return this;
}
public OllamaStreamingChatModelBuilder topK(Integer topK) {
this.topK = topK;
return this;
}
public OllamaStreamingChatModelBuilder topP(Double topP) {
this.topP = topP;
return this;
}
public OllamaStreamingChatModelBuilder repeatPenalty(Double repeatPenalty) {
this.repeatPenalty = repeatPenalty;
return this;
}
public OllamaStreamingChatModelBuilder seed(Integer seed) {
this.seed = seed;
return this;
}
public OllamaStreamingChatModelBuilder numPredict(Integer numPredict) {
this.numPredict = numPredict;
return this;
}
public OllamaStreamingChatModelBuilder numCtx(Integer numCtx) {
this.numCtx = numCtx;
return this;
}
public OllamaStreamingChatModelBuilder stop(List<String> stop) {
this.stop = stop;
return this;
}
public OllamaStreamingChatModelBuilder format(String format) {
this.format = format;
return this;
}
public OllamaStreamingChatModelBuilder timeout(Duration timeout) {
this.timeout = timeout;
return this;
}
public OllamaStreamingChatModelBuilder customHeaders(Map<String, String> customHeaders) {
this.customHeaders = customHeaders;
return this;
}
public OllamaStreamingChatModelBuilder logRequests(Boolean logRequests) {
this.logRequests = logRequests;
return this;
}
public OllamaStreamingChatModelBuilder logResponses(Boolean logResponses) {
this.logResponses = logResponses;
return this;
}
public OllamaStreamingChatModel build() {
return new OllamaStreamingChatModel(
baseUrl,
modelName,
temperature,
topK,
topP,
repeatPenalty,
seed,
numPredict,
numCtx,
stop,
format,
timeout,
logRequests,
logResponses,
customHeaders
);
}
}
}

View File

@ -3,7 +3,6 @@ package dev.langchain4j.model.ollama;
import dev.langchain4j.model.StreamingResponseHandler;
import dev.langchain4j.model.language.StreamingLanguageModel;
import dev.langchain4j.model.ollama.spi.OllamaStreamingLanguageModelBuilderFactory;
import lombok.Builder;
import java.time.Duration;
import java.util.List;
@ -26,7 +25,6 @@ public class OllamaStreamingLanguageModel implements StreamingLanguageModel {
private final Options options;
private final String format;
@Builder
public OllamaStreamingLanguageModel(String baseUrl,
String modelName,
Double temperature,
@ -42,7 +40,7 @@ public class OllamaStreamingLanguageModel implements StreamingLanguageModel {
Boolean logRequests,
Boolean logResponses,
Map<String, String> customHeaders
) {
) {
this.client = OllamaClient.builder()
.baseUrl(baseUrl)
.timeout(getOrDefault(timeout, ofSeconds(60)))
@ -64,6 +62,13 @@ public class OllamaStreamingLanguageModel implements StreamingLanguageModel {
this.format = format;
}
public static OllamaStreamingLanguageModelBuilder builder() {
for (OllamaStreamingLanguageModelBuilderFactory factory : loadFactories(OllamaStreamingLanguageModelBuilderFactory.class)) {
return factory.get();
}
return new OllamaStreamingLanguageModelBuilder();
}
@Override
public void generate(String prompt, StreamingResponseHandler<String> handler) {
CompletionRequest request = CompletionRequest.builder()
@ -77,17 +82,122 @@ public class OllamaStreamingLanguageModel implements StreamingLanguageModel {
client.streamingCompletion(request, handler);
}
public static OllamaStreamingLanguageModelBuilder builder() {
for (OllamaStreamingLanguageModelBuilderFactory factory : loadFactories(OllamaStreamingLanguageModelBuilderFactory.class)) {
return factory.get();
}
return new OllamaStreamingLanguageModelBuilder();
}
public static class OllamaStreamingLanguageModelBuilder {
private String baseUrl;
private String modelName;
private Double temperature;
private Integer topK;
private Double topP;
private Double repeatPenalty;
private Integer seed;
private Integer numPredict;
private Integer numCtx;
private List<String> stop;
private String format;
private Duration timeout;
private Map<String, String> customHeaders;
private Boolean logRequests;
private Boolean logResponses;
public OllamaStreamingLanguageModelBuilder() {
// This is public so it can be extended
// By default with Lombok it becomes package private
}
public OllamaStreamingLanguageModelBuilder baseUrl(String baseUrl) {
this.baseUrl = baseUrl;
return this;
}
public OllamaStreamingLanguageModelBuilder modelName(String modelName) {
this.modelName = modelName;
return this;
}
public OllamaStreamingLanguageModelBuilder temperature(Double temperature) {
this.temperature = temperature;
return this;
}
public OllamaStreamingLanguageModelBuilder topK(Integer topK) {
this.topK = topK;
return this;
}
public OllamaStreamingLanguageModelBuilder topP(Double topP) {
this.topP = topP;
return this;
}
public OllamaStreamingLanguageModelBuilder repeatPenalty(Double repeatPenalty) {
this.repeatPenalty = repeatPenalty;
return this;
}
public OllamaStreamingLanguageModelBuilder seed(Integer seed) {
this.seed = seed;
return this;
}
public OllamaStreamingLanguageModelBuilder numPredict(Integer numPredict) {
this.numPredict = numPredict;
return this;
}
public OllamaStreamingLanguageModelBuilder numCtx(Integer numCtx) {
this.numCtx = numCtx;
return this;
}
public OllamaStreamingLanguageModelBuilder stop(List<String> stop) {
this.stop = stop;
return this;
}
public OllamaStreamingLanguageModelBuilder format(String format) {
this.format = format;
return this;
}
public OllamaStreamingLanguageModelBuilder timeout(Duration timeout) {
this.timeout = timeout;
return this;
}
public OllamaStreamingLanguageModelBuilder customHeaders(Map<String, String> customHeaders) {
this.customHeaders = customHeaders;
return this;
}
public OllamaStreamingLanguageModelBuilder logRequests(Boolean logRequests) {
this.logRequests = logRequests;
return this;
}
public OllamaStreamingLanguageModelBuilder logResponses(Boolean logResponses) {
this.logResponses = logResponses;
return this;
}
public OllamaStreamingLanguageModel build() {
return new OllamaStreamingLanguageModel(
baseUrl,
modelName,
temperature,
topK,
topP,
repeatPenalty,
seed,
numPredict,
numCtx,
stop,
format,
timeout,
logRequests,
logResponses,
customHeaders
);
}
}
}

View File

@ -4,10 +4,6 @@ import com.fasterxml.jackson.annotation.JsonIgnoreProperties;
import com.fasterxml.jackson.annotation.JsonInclude;
import com.fasterxml.jackson.databind.PropertyNamingStrategies.SnakeCaseStrategy;
import com.fasterxml.jackson.databind.annotation.JsonNaming;
import lombok.AllArgsConstructor;
import lombok.Builder;
import lombok.Data;
import lombok.NoArgsConstructor;
import java.util.List;
@ -18,10 +14,6 @@ import static com.fasterxml.jackson.annotation.JsonInclude.Include.NON_NULL;
*
* @see <a href="https://github.com/jmorganca/ollama/blob/main/docs/modelfile.md#valid-parameters-and-values">Ollama REST API Doc</a>
*/
@Data
@NoArgsConstructor
@AllArgsConstructor
@Builder
@JsonIgnoreProperties(ignoreUnknown = true)
@JsonInclude(NON_NULL)
@JsonNaming(SnakeCaseStrategy.class)
@ -35,4 +27,142 @@ class Options {
private Integer numPredict;
private Integer numCtx;
private List<String> stop;
Options() {
}
Options(Double temperature, Integer topK, Double topP, Double repeatPenalty, Integer seed, Integer numPredict, Integer numCtx, List<String> stop) {
this.temperature = temperature;
this.topK = topK;
this.topP = topP;
this.repeatPenalty = repeatPenalty;
this.seed = seed;
this.numPredict = numPredict;
this.numCtx = numCtx;
this.stop = stop;
}
static Builder builder() {
return new Builder();
}
public Double getTemperature() {
return temperature;
}
public void setTemperature(Double temperature) {
this.temperature = temperature;
}
public Integer getTopK() {
return topK;
}
public void setTopK(Integer topK) {
this.topK = topK;
}
public Double getTopP() {
return topP;
}
public void setTopP(Double topP) {
this.topP = topP;
}
public Double getRepeatPenalty() {
return repeatPenalty;
}
public void setRepeatPenalty(Double repeatPenalty) {
this.repeatPenalty = repeatPenalty;
}
public Integer getNumPredict() {
return numPredict;
}
public void setNumPredict(Integer numPredict) {
this.numPredict = numPredict;
}
public Integer getSeed() {
return seed;
}
public void setSeed(Integer seed) {
this.seed = seed;
}
public Integer getNumCtx() {
return numCtx;
}
public void setNumCtx(Integer numCtx) {
this.numCtx = numCtx;
}
public List<String> getStop() {
return stop;
}
public void setStop(List<String> stop) {
this.stop = stop;
}
static class Builder {
private Double temperature;
private Integer topK;
private Double topP;
private Double repeatPenalty;
private Integer seed;
private Integer numPredict;
private Integer numCtx;
private List<String> stop;
Builder temperature(Double temperature) {
this.temperature = temperature;
return this;
}
Builder topK(Integer topK) {
this.topK = topK;
return this;
}
Builder topP(Double topP) {
this.topP = topP;
return this;
}
Builder repeatPenalty(Double repeatPenalty) {
this.repeatPenalty = repeatPenalty;
return this;
}
Builder seed(Integer seed) {
this.seed = seed;
return this;
}
Builder numPredict(Integer numPredict) {
this.numPredict = numPredict;
return this;
}
Builder numCtx(Integer numCtx) {
this.numCtx = numCtx;
return this;
}
Builder stop(List<String> stop) {
this.stop = stop;
return this;
}
Options build() {
return new Options(temperature, topK, topP, repeatPenalty, seed, numPredict, numCtx, stop);
}
}
}

View File

@ -4,25 +4,81 @@ import com.fasterxml.jackson.annotation.JsonIgnoreProperties;
import com.fasterxml.jackson.annotation.JsonInclude;
import com.fasterxml.jackson.databind.PropertyNamingStrategies;
import com.fasterxml.jackson.databind.annotation.JsonNaming;
import lombok.AllArgsConstructor;
import lombok.Builder;
import lombok.Data;
import lombok.NoArgsConstructor;
import java.util.List;
import java.util.Map;
import static com.fasterxml.jackson.annotation.JsonInclude.Include.NON_NULL;
@Data
@NoArgsConstructor
@AllArgsConstructor
@Builder
@JsonIgnoreProperties(ignoreUnknown = true)
@JsonInclude(NON_NULL)
@JsonNaming(PropertyNamingStrategies.SnakeCaseStrategy.class)
class Parameters {
private String type = "object";
private Map<String, Map<String,Object>> properties;
private String type;
private Map<String, Map<String, Object>> properties;
private List<String> required;
Parameters() {
}
Parameters(String type, Map<String, Map<String, Object>> properties, List<String> required) {
this.type = type;
this.properties = properties;
this.required = required;
}
static Builder builder() {
return new Builder();
}
public String getType() {
return type;
}
public void setType(String type) {
this.type = type;
}
public Map<String, Map<String, Object>> getProperties() {
return properties;
}
public void setProperties(Map<String, Map<String, Object>> properties) {
this.properties = properties;
}
public List<String> getRequired() {
return required;
}
public void setRequired(List<String> required) {
this.required = required;
}
static class Builder {
private String type = "object";
private Map<String, Map<String, Object>> properties;
private List<String> required;
Builder type(String type) {
this.type = type;
return this;
}
Builder properties(Map<String, Map<String, Object>> properties) {
this.properties = properties;
return this;
}
Builder required(List<String> required) {
this.required = required;
return this;
}
Parameters build() {
return new Parameters(type, properties, required);
}
}
}

View File

@ -4,23 +4,49 @@ import com.fasterxml.jackson.annotation.JsonIgnoreProperties;
import com.fasterxml.jackson.annotation.JsonInclude;
import com.fasterxml.jackson.databind.PropertyNamingStrategies.SnakeCaseStrategy;
import com.fasterxml.jackson.databind.annotation.JsonNaming;
import lombok.AllArgsConstructor;
import lombok.Builder;
import lombok.Data;
import lombok.NoArgsConstructor;
import java.util.List;
import static com.fasterxml.jackson.annotation.JsonInclude.Include.NON_NULL;
@Data
@NoArgsConstructor
@AllArgsConstructor
@Builder
@JsonIgnoreProperties(ignoreUnknown = true)
@JsonInclude(NON_NULL)
@JsonNaming(SnakeCaseStrategy.class)
class RunningModelsListResponse {
private List<RunningOllamaModel> models;
RunningModelsListResponse() {
}
RunningModelsListResponse(List<RunningOllamaModel> models) {
this.models = models;
}
public List<RunningOllamaModel> getModels() {
return models;
}
public void setModels(List<RunningOllamaModel> models) {
this.models = models;
}
static Builder builder() {
return new Builder();
}
static class Builder {
private List<RunningOllamaModel> models;
Builder models(List<RunningOllamaModel> models) {
this.models = models;
return this;
}
RunningModelsListResponse build() {
return new RunningModelsListResponse(models);
}
}
}

View File

@ -5,19 +5,11 @@ import com.fasterxml.jackson.annotation.JsonInclude;
import com.fasterxml.jackson.databind.PropertyNamingStrategies;
import com.fasterxml.jackson.databind.annotation.JsonDeserialize;
import com.fasterxml.jackson.databind.annotation.JsonNaming;
import lombok.AllArgsConstructor;
import lombok.Builder;
import lombok.Data;
import lombok.NoArgsConstructor;
import java.time.OffsetDateTime;
import static com.fasterxml.jackson.annotation.JsonInclude.Include.NON_NULL;
@Data
@NoArgsConstructor
@AllArgsConstructor
@Builder
@JsonIgnoreProperties(ignoreUnknown = true)
@JsonInclude(NON_NULL)
@JsonNaming(PropertyNamingStrategies.SnakeCaseStrategy.class)
@ -32,4 +24,126 @@ public class RunningOllamaModel {
private OffsetDateTime expiresAt;
private Long sizeVram;
RunningOllamaModel() {
}
RunningOllamaModel(String name, String model, Long size, OllamaModelDetails details, String digest, OffsetDateTime expiresAt, Long sizeVram) {
this.name = name;
this.model = model;
this.size = size;
this.details = details;
this.digest = digest;
this.expiresAt = expiresAt;
this.sizeVram = sizeVram;
}
public String getName() {
return name;
}
public void setName(String name) {
this.name = name;
}
public String getModel() {
return model;
}
public void setModel(String model) {
this.model = model;
}
public Long getSize() {
return size;
}
public void setSize(Long size) {
this.size = size;
}
public String getDigest() {
return digest;
}
public void setDigest(String digest) {
this.digest = digest;
}
public OllamaModelDetails getDetails() {
return details;
}
public void setDetails(OllamaModelDetails details) {
this.details = details;
}
public OffsetDateTime getExpiresAt() {
return expiresAt;
}
public void setExpiresAt(OffsetDateTime expiresAt) {
this.expiresAt = expiresAt;
}
public Long getSizeVram() {
return sizeVram;
}
public void setSizeVram(Long sizeVram) {
this.sizeVram = sizeVram;
}
static Builder builder() {
return new Builder();
}
static class Builder {
private String name;
private String model;
private Long size;
private String digest;
private OllamaModelDetails details;
private OffsetDateTime expiresAt;
private Long sizeVram;
Builder name(String name) {
this.name = name;
return this;
}
Builder model(String model) {
this.model = model;
return this;
}
Builder size(Long size) {
this.size = size;
return this;
}
Builder digest(String digest) {
this.digest = digest;
return this;
}
Builder details(OllamaModelDetails details) {
this.details = details;
return this;
}
Builder expiresAt(OffsetDateTime expiresAt) {
this.expiresAt = expiresAt;
return this;
}
Builder sizeVram(Long sizeVram) {
this.sizeVram = sizeVram;
return this;
}
RunningOllamaModel build() {
return new RunningOllamaModel(name, model, size, details, digest, expiresAt, sizeVram);
}
}
}

View File

@ -4,21 +4,46 @@ import com.fasterxml.jackson.annotation.JsonIgnoreProperties;
import com.fasterxml.jackson.annotation.JsonInclude;
import com.fasterxml.jackson.databind.PropertyNamingStrategies.SnakeCaseStrategy;
import com.fasterxml.jackson.databind.annotation.JsonNaming;
import lombok.AllArgsConstructor;
import lombok.Builder;
import lombok.Data;
import lombok.NoArgsConstructor;
import static com.fasterxml.jackson.annotation.JsonInclude.Include.NON_NULL;
@Data
@NoArgsConstructor
@AllArgsConstructor
@Builder
@JsonIgnoreProperties(ignoreUnknown = true)
@JsonInclude(NON_NULL)
@JsonNaming(SnakeCaseStrategy.class)
class ShowModelInformationRequest {
private String name;
ShowModelInformationRequest() {
}
ShowModelInformationRequest(String name) {
this.name = name;
}
static Builder builder() {
return new Builder();
}
public String getName() {
return name;
}
public void setName(String name) {
this.name = name;
}
static class Builder {
private String name;
Builder name(String name) {
this.name = name;
return this;
}
ShowModelInformationRequest build() {
return new ShowModelInformationRequest(name);
}
}
}

View File

@ -2,23 +2,59 @@ package dev.langchain4j.model.ollama;
import com.fasterxml.jackson.annotation.JsonIgnoreProperties;
import com.fasterxml.jackson.annotation.JsonInclude;
import com.fasterxml.jackson.databind.PropertyNamingStrategies;
import com.fasterxml.jackson.databind.PropertyNamingStrategies.SnakeCaseStrategy;
import com.fasterxml.jackson.databind.annotation.JsonNaming;
import lombok.AllArgsConstructor;
import lombok.Builder;
import lombok.Data;
import lombok.NoArgsConstructor;
import static com.fasterxml.jackson.annotation.JsonInclude.Include.NON_NULL;
@Data
@NoArgsConstructor
@AllArgsConstructor
@Builder
@JsonIgnoreProperties(ignoreUnknown = true)
@JsonInclude(NON_NULL)
@JsonNaming(PropertyNamingStrategies.SnakeCaseStrategy.class)
@JsonNaming(SnakeCaseStrategy.class)
class Tool {
private final String type = "function";
private String type;
private Function function;
Tool() {
}
Tool(String type, Function function) {
this.type = type;
this.function = function;
}
static Builder builder() {
return new Builder();
}
public String getType() {
return type;
}
public void setType(String type) {
this.type = type;
}
public Function getFunction() {
return function;
}
public void setFunction(Function function) {
this.function = function;
}
static class Builder {
private final String type = "function";
private Function function;
Builder function(Function function) {
this.function = function;
return this;
}
Tool build() {
return new Tool(type, function);
}
}
}

View File

@ -4,20 +4,46 @@ import com.fasterxml.jackson.annotation.JsonIgnoreProperties;
import com.fasterxml.jackson.annotation.JsonInclude;
import com.fasterxml.jackson.databind.PropertyNamingStrategies;
import com.fasterxml.jackson.databind.annotation.JsonNaming;
import lombok.AllArgsConstructor;
import lombok.Builder;
import lombok.Data;
import lombok.NoArgsConstructor;
import static com.fasterxml.jackson.annotation.JsonInclude.Include.NON_NULL;
@Data
@NoArgsConstructor
@AllArgsConstructor
@Builder
@JsonIgnoreProperties(ignoreUnknown = true)
@JsonInclude(NON_NULL)
@JsonNaming(PropertyNamingStrategies.SnakeCaseStrategy.class)
class ToolCall {
private FunctionCall function;
ToolCall() {
}
ToolCall(FunctionCall function) {
this.function = function;
}
static Builder builder() {
return new Builder();
}
public FunctionCall getFunction() {
return function;
}
public void setFunction(FunctionCall function) {
this.function = function;
}
static class Builder {
private FunctionCall function;
Builder function(FunctionCall function) {
this.function = function;
return this;
}
ToolCall build() {
return new ToolCall(function);
}
}
}

View File

@ -1,15 +1,17 @@
package dev.langchain4j.model.ollama;
import com.github.dockerjava.api.command.InspectContainerResponse;
import lombok.extern.slf4j.Slf4j;
import org.slf4j.Logger;
import org.slf4j.LoggerFactory;
import org.testcontainers.ollama.OllamaContainer;
import org.testcontainers.utility.DockerImageName;
import java.io.IOException;
@Slf4j
public class LangChain4jOllamaContainer extends OllamaContainer {
private static final Logger log = LoggerFactory.getLogger(LangChain4jOllamaContainer.class);
private final DockerImageName dockerImageName;
private String model;