diff --git a/models/spring-ai-ollama/src/main/java/org/springframework/ai/ollama/OllamaChatModel.java b/models/spring-ai-ollama/src/main/java/org/springframework/ai/ollama/OllamaChatModel.java index c6bd6c2676e..edcc5a6e9f9 100644 --- a/models/spring-ai-ollama/src/main/java/org/springframework/ai/ollama/OllamaChatModel.java +++ b/models/spring-ai-ollama/src/main/java/org/springframework/ai/ollama/OllamaChatModel.java @@ -491,6 +491,10 @@ else if (message instanceof ToolResponseMessage toolMessage) { requestBuilder.keepAlive(requestOptions.getKeepAlive()); } + if (requestOptions.getThink() != null) { + requestBuilder.think(requestOptions.getThink()); + } + List toolDefinitions = this.toolCallingManager.resolveToolDefinitions(requestOptions); if (!CollectionUtils.isEmpty(toolDefinitions)) { requestBuilder.tools(this.getTools(toolDefinitions)); diff --git a/models/spring-ai-ollama/src/main/java/org/springframework/ai/ollama/api/OllamaOptions.java b/models/spring-ai-ollama/src/main/java/org/springframework/ai/ollama/api/OllamaOptions.java index 64da524c653..e216bb6d664 100644 --- a/models/spring-ai-ollama/src/main/java/org/springframework/ai/ollama/api/OllamaOptions.java +++ b/models/spring-ai-ollama/src/main/java/org/springframework/ai/ollama/api/OllamaOptions.java @@ -351,9 +351,16 @@ public class OllamaOptions implements ToolCallingChatOptions, EmbeddingOptions { @JsonProperty("truncate") private Boolean truncate; + /** + * Think controls whether thinking/reasoning models will think before responding. + */ + @JsonProperty("think") + private Boolean think; + @JsonIgnore private Boolean internalToolExecutionEnabled; + /** * Tool Function Callbacks to register with the ChatModel. * For Prompt Options the toolCallbacks are automatically enabled for the duration of the prompt execution. @@ -398,6 +405,7 @@ public static OllamaOptions fromOptions(OllamaOptions fromOptions) { .format(fromOptions.getFormat()) .keepAlive(fromOptions.getKeepAlive()) .truncate(fromOptions.getTruncate()) + .think(fromOptions.getThink()) .useNUMA(fromOptions.getUseNUMA()) .numCtx(fromOptions.getNumCtx()) .numBatch(fromOptions.getNumBatch()) @@ -825,6 +833,13 @@ public void setTruncate(Boolean truncate) { this.truncate = truncate; } + public Boolean getThink() { + return this.think; + } + public void setThink(Boolean think) { + this.think = think; + } + @Override @JsonIgnore public List getToolCallbacks() { @@ -910,17 +925,17 @@ public boolean equals(Object o) { OllamaOptions that = (OllamaOptions) o; return Objects.equals(this.model, that.model) && Objects.equals(this.format, that.format) && Objects.equals(this.keepAlive, that.keepAlive) && Objects.equals(this.truncate, that.truncate) - && Objects.equals(this.useNUMA, that.useNUMA) && Objects.equals(this.numCtx, that.numCtx) - && Objects.equals(this.numBatch, that.numBatch) && Objects.equals(this.numGPU, that.numGPU) - && Objects.equals(this.mainGPU, that.mainGPU) && Objects.equals(this.lowVRAM, that.lowVRAM) - && Objects.equals(this.f16KV, that.f16KV) && Objects.equals(this.logitsAll, that.logitsAll) - && Objects.equals(this.vocabOnly, that.vocabOnly) && Objects.equals(this.useMMap, that.useMMap) - && Objects.equals(this.useMLock, that.useMLock) && Objects.equals(this.numThread, that.numThread) - && Objects.equals(this.numKeep, that.numKeep) && Objects.equals(this.seed, that.seed) - && Objects.equals(this.numPredict, that.numPredict) && Objects.equals(this.topK, that.topK) - && Objects.equals(this.topP, that.topP) && Objects.equals(this.minP, that.minP) - && Objects.equals(this.tfsZ, that.tfsZ) && Objects.equals(this.typicalP, that.typicalP) - && Objects.equals(this.repeatLastN, that.repeatLastN) + && Objects.equals(this.think, that.think) && Objects.equals(this.useNUMA, that.useNUMA) + && Objects.equals(this.numCtx, that.numCtx) && Objects.equals(this.numBatch, that.numBatch) + && Objects.equals(this.numGPU, that.numGPU) && Objects.equals(this.mainGPU, that.mainGPU) + && Objects.equals(this.lowVRAM, that.lowVRAM) && Objects.equals(this.f16KV, that.f16KV) + && Objects.equals(this.logitsAll, that.logitsAll) && Objects.equals(this.vocabOnly, that.vocabOnly) + && Objects.equals(this.useMMap, that.useMMap) && Objects.equals(this.useMLock, that.useMLock) + && Objects.equals(this.numThread, that.numThread) && Objects.equals(this.numKeep, that.numKeep) + && Objects.equals(this.seed, that.seed) && Objects.equals(this.numPredict, that.numPredict) + && Objects.equals(this.topK, that.topK) && Objects.equals(this.topP, that.topP) + && Objects.equals(this.minP, that.minP) && Objects.equals(this.tfsZ, that.tfsZ) + && Objects.equals(this.typicalP, that.typicalP) && Objects.equals(this.repeatLastN, that.repeatLastN) && Objects.equals(this.temperature, that.temperature) && Objects.equals(this.repeatPenalty, that.repeatPenalty) && Objects.equals(this.presencePenalty, that.presencePenalty) @@ -935,13 +950,13 @@ public boolean equals(Object o) { @Override public int hashCode() { - return Objects.hash(this.model, this.format, this.keepAlive, this.truncate, this.useNUMA, this.numCtx, - this.numBatch, this.numGPU, this.mainGPU, this.lowVRAM, this.f16KV, this.logitsAll, this.vocabOnly, - this.useMMap, this.useMLock, this.numThread, this.numKeep, this.seed, this.numPredict, this.topK, - this.topP, this.minP, this.tfsZ, this.typicalP, this.repeatLastN, this.temperature, this.repeatPenalty, - this.presencePenalty, this.frequencyPenalty, this.mirostat, this.mirostatTau, this.mirostatEta, - this.penalizeNewline, this.stop, this.toolCallbacks, this.toolNames, this.internalToolExecutionEnabled, - this.toolContext); + return Objects.hash(this.model, this.format, this.keepAlive, this.truncate, this.think, this.useNUMA, + this.numCtx, this.numBatch, this.numGPU, this.mainGPU, this.lowVRAM, this.f16KV, this.logitsAll, + this.vocabOnly, this.useMMap, this.useMLock, this.numThread, this.numKeep, this.seed, this.numPredict, + this.topK, this.topP, this.minP, this.tfsZ, this.typicalP, this.repeatLastN, this.temperature, + this.repeatPenalty, this.presencePenalty, this.frequencyPenalty, this.mirostat, this.mirostatTau, + this.mirostatEta, this.penalizeNewline, this.stop, this.toolCallbacks, this.toolNames, + this.internalToolExecutionEnabled, this.toolContext); } public static class Builder { @@ -1204,6 +1219,11 @@ public Builder toolContext(Map toolContext) { return this; } + public Builder think(@Nullable Boolean think) { + this.options.setThink(think); + return this; + } + public OllamaOptions build() { return this.options; }