@@ -317,6 +317,31 @@ public class OllamaChatOptions implements ToolCallingChatOptions {
317317 @ JsonProperty ("truncate" )
318318 private Boolean truncate ;
319319
320+ /**
321+ * The model should think before responding, if supported.
322+ * <p>
323+ * Most models (Qwen 3, DeepSeek-v3.1, DeepSeek R1) use boolean enable/disable.
324+ * The GPT-OSS model requires string levels: "low", "medium", or "high".
325+ * <p>
326+ * <strong>Default Behavior (Ollama 0.12+):</strong>
327+ * <ul>
328+ * <li>Thinking-capable models (e.g., qwen3:*-thinking, deepseek-r1, deepseek-v3.1)
329+ * <strong>auto-enable thinking by default</strong> when this field is not set.</li>
330+ * <li>Standard models (e.g., qwen2.5:*, llama3.2) do not enable thinking by default.</li>
331+ * <li>To explicitly control behavior, use {@link Builder#enableThinking()} or
332+ * {@link Builder#disableThinking()}.</li>
333+ * </ul>
334+ * <p>
335+ * Use {@link Builder#enableThinking()}, {@link Builder#disableThinking()}, or
336+ * {@link Builder#thinkHigh()} to configure this option.
337+ *
338+ * @see ThinkOption
339+ * @see ThinkOption.ThinkBoolean
340+ * @see ThinkOption.ThinkLevel
341+ */
342+ @ JsonProperty ("think" )
343+ private ThinkOption thinkOption ;
344+
320345 @ JsonIgnore
321346 private Boolean internalToolExecutionEnabled ;
322347
@@ -364,6 +389,7 @@ public static OllamaChatOptions fromOptions(OllamaChatOptions fromOptions) {
364389 .format (fromOptions .getFormat ())
365390 .keepAlive (fromOptions .getKeepAlive ())
366391 .truncate (fromOptions .getTruncate ())
392+ .thinkOption (fromOptions .getThinkOption ())
367393 .useNUMA (fromOptions .getUseNUMA ())
368394 .numCtx (fromOptions .getNumCtx ())
369395 .numBatch (fromOptions .getNumBatch ())
@@ -745,6 +771,14 @@ public void setTruncate(Boolean truncate) {
745771 this .truncate = truncate ;
746772 }
747773
774+ public ThinkOption getThinkOption () {
775+ return this .thinkOption ;
776+ }
777+
778+ public void setThinkOption (ThinkOption thinkOption ) {
779+ this .thinkOption = thinkOption ;
780+ }
781+
748782 @ Override
749783 @ JsonIgnore
750784 public List <ToolCallback > getToolCallbacks () {
@@ -824,17 +858,17 @@ public boolean equals(Object o) {
824858 OllamaChatOptions that = (OllamaChatOptions ) o ;
825859 return Objects .equals (this .model , that .model ) && Objects .equals (this .format , that .format )
826860 && Objects .equals (this .keepAlive , that .keepAlive ) && Objects .equals (this .truncate , that .truncate )
827- && Objects .equals (this .useNUMA , that .useNUMA ) && Objects .equals (this .numCtx , that .numCtx )
828- && Objects .equals (this .numBatch , that .numBatch ) && Objects .equals (this .numGPU , that .numGPU )
829- && Objects .equals (this .mainGPU , that .mainGPU ) && Objects .equals (this .lowVRAM , that .lowVRAM )
830- && Objects .equals (this .f16KV , that .f16KV ) && Objects .equals (this .logitsAll , that .logitsAll )
831- && Objects .equals (this .vocabOnly , that .vocabOnly ) && Objects .equals (this .useMMap , that .useMMap )
832- && Objects .equals (this .useMLock , that .useMLock ) && Objects .equals (this .numThread , that .numThread )
833- && Objects .equals (this .numKeep , that .numKeep ) && Objects .equals (this .seed , that .seed )
834- && Objects .equals (this .numPredict , that .numPredict ) && Objects .equals (this .topK , that .topK )
835- && Objects .equals (this .topP , that .topP ) && Objects .equals (this .minP , that .minP )
836- && Objects .equals (this .tfsZ , that .tfsZ ) && Objects .equals (this .typicalP , that .typicalP )
837- && Objects .equals (this .repeatLastN , that .repeatLastN )
861+ && Objects .equals (this .thinkOption , that .thinkOption ) && Objects .equals (this .useNUMA , that .useNUMA )
862+ && Objects .equals (this .numCtx , that .numCtx ) && Objects .equals (this .numBatch , that .numBatch )
863+ && Objects .equals (this .numGPU , that .numGPU ) && Objects .equals (this .mainGPU , that .mainGPU )
864+ && Objects .equals (this .lowVRAM , that .lowVRAM ) && Objects .equals (this .f16KV , that .f16KV )
865+ && Objects .equals (this .logitsAll , that .logitsAll ) && Objects .equals (this .vocabOnly , that .vocabOnly )
866+ && Objects .equals (this .useMMap , that .useMMap ) && Objects .equals (this .useMLock , that .useMLock )
867+ && Objects .equals (this .numThread , that .numThread ) && Objects .equals (this .numKeep , that .numKeep )
868+ && Objects .equals (this .seed , that .seed ) && Objects .equals (this .numPredict , that .numPredict )
869+ && Objects .equals (this .topK , that .topK ) && Objects .equals (this .topP , that .topP )
870+ && Objects .equals (this .minP , that .minP ) && Objects .equals (this .tfsZ , that .tfsZ )
871+ && Objects .equals (this .typicalP , that . typicalP ) && Objects . equals ( this . repeatLastN , that .repeatLastN )
838872 && Objects .equals (this .temperature , that .temperature )
839873 && Objects .equals (this .repeatPenalty , that .repeatPenalty )
840874 && Objects .equals (this .presencePenalty , that .presencePenalty )
@@ -849,13 +883,13 @@ public boolean equals(Object o) {
849883
850884 @ Override
851885 public int hashCode () {
852- return Objects .hash (this .model , this .format , this .keepAlive , this .truncate , this .useNUMA , this .numCtx ,
853- this .numBatch , this .numGPU , this .mainGPU , this .lowVRAM , this .f16KV , this .logitsAll , this . vocabOnly ,
854- this .useMMap , this .useMLock , this .numThread , this .numKeep , this .seed , this .numPredict , this . topK ,
855- this .topP , this .minP , this .tfsZ , this .typicalP , this .repeatLastN , this .temperature , this . repeatPenalty ,
856- this .presencePenalty , this .frequencyPenalty , this .mirostat , this .mirostatTau , this .mirostatEta ,
857- this .penalizeNewline , this .stop , this .toolCallbacks , this .toolNames , this .internalToolExecutionEnabled ,
858- this .toolContext );
886+ return Objects .hash (this .model , this .format , this .keepAlive , this .truncate , this .thinkOption , this .useNUMA ,
887+ this .numCtx , this . numBatch , this .numGPU , this .mainGPU , this .lowVRAM , this .f16KV , this .logitsAll ,
888+ this .vocabOnly , this . useMMap , this .useMLock , this .numThread , this .numKeep , this .seed , this .numPredict ,
889+ this .topK , this . topP , this .minP , this .tfsZ , this .typicalP , this .repeatLastN , this .temperature ,
890+ this .repeatPenalty , this .presencePenalty , this .frequencyPenalty , this .mirostat , this .mirostatTau ,
891+ this .mirostatEta , this .penalizeNewline , this .stop , this .toolCallbacks , this .toolNames ,
892+ this .internalToolExecutionEnabled , this . toolContext );
859893 }
860894
861895 public static final class Builder {
@@ -1037,6 +1071,78 @@ public Builder stop(List<String> stop) {
10371071 return this ;
10381072 }
10391073
1074+ /**
1075+ * Enable thinking mode for the model. The model will include its reasoning
1076+ * process in the response's thinking field.
1077+ * <p>
1078+ * Supported by models: Qwen 3, DeepSeek-v3.1, DeepSeek R1
1079+ * @return this builder
1080+ * @see #disableThinking()
1081+ * @see #thinkLow()
1082+ */
1083+ public Builder enableThinking () {
1084+ this .options .thinkOption = ThinkOption .ThinkBoolean .ENABLED ;
1085+ return this ;
1086+ }
1087+
1088+ /**
1089+ * Disable thinking mode for the model.
1090+ * @return this builder
1091+ * @see #enableThinking()
1092+ */
1093+ public Builder disableThinking () {
1094+ this .options .thinkOption = ThinkOption .ThinkBoolean .DISABLED ;
1095+ return this ;
1096+ }
1097+
1098+ /**
1099+ * Set thinking level to "low" (for GPT-OSS model).
1100+ * <p>
1101+ * GPT-OSS requires one of: low, medium, high. Boolean enable/disable is not
1102+ * supported for this model.
1103+ * @return this builder
1104+ * @see #thinkMedium()
1105+ * @see #thinkHigh()
1106+ */
1107+ public Builder thinkLow () {
1108+ this .options .thinkOption = ThinkOption .ThinkLevel .LOW ;
1109+ return this ;
1110+ }
1111+
1112+ /**
1113+ * Set thinking level to "medium" (for GPT-OSS model).
1114+ * @return this builder
1115+ * @see #thinkLow()
1116+ * @see #thinkHigh()
1117+ */
1118+ public Builder thinkMedium () {
1119+ this .options .thinkOption = ThinkOption .ThinkLevel .MEDIUM ;
1120+ return this ;
1121+ }
1122+
1123+ /**
1124+ * Set thinking level to "high" (for GPT-OSS model).
1125+ * @return this builder
1126+ * @see #thinkLow()
1127+ * @see #thinkMedium()
1128+ */
1129+ public Builder thinkHigh () {
1130+ this .options .thinkOption = ThinkOption .ThinkLevel .HIGH ;
1131+ return this ;
1132+ }
1133+
1134+ /**
1135+ * Set the think option explicitly. Use {@link #enableThinking()},
1136+ * {@link #disableThinking()}, {@link #thinkLow()}, {@link #thinkMedium()}, or
1137+ * {@link #thinkHigh()} for more convenient alternatives.
1138+ * @param thinkOption the think option
1139+ * @return this builder
1140+ */
1141+ public Builder thinkOption (ThinkOption thinkOption ) {
1142+ this .options .thinkOption = thinkOption ;
1143+ return this ;
1144+ }
1145+
10401146 public Builder toolCallbacks (List <ToolCallback > toolCallbacks ) {
10411147 this .options .setToolCallbacks (toolCallbacks );
10421148 return this ;
0 commit comments