Skip to content
Open
Show file tree
Hide file tree
Changes from all commits
Commits
File filter

Filter by extension

Filter by extension

Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
2 changes: 1 addition & 1 deletion dotnet/Directory.Packages.props
Original file line number Diff line number Diff line change
Expand Up @@ -93,7 +93,7 @@
<PackageVersion Include="Newtonsoft.Json" Version="13.0.4" />
<PackageVersion Include="Npgsql" Version="10.0.2" />
<PackageVersion Include="OData2Linq" Version="2.2.0" />
<PackageVersion Include="OllamaSharp" Version="5.4.12" />
<PackageVersion Include="OllamaSharp" Version="5.4.25" />
<PackageVersion Include="OpenAI" Version="2.10.0" />
<PackageVersion Include="OpenTelemetry" Version="1.15.3" />
<PackageVersion Include="OpenTelemetry.Api" Version="1.15.3" />
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -188,6 +188,57 @@ public async Task GetTextContentsExecutionSettingsMustBeSentAsync()
Assert.Equal(ollamaExecutionSettings.TopK, requestPayload.Options.TopK);
}

[Theory]
[InlineData(true)]
[InlineData(false)]
public async Task GetTextContentsShouldSendThinkSettingAsync(bool thinkValue)
{
// Arrange
var sut = new OllamaTextGenerationService("fake-model", httpClient: this._httpClient);
var settings = new OllamaPromptExecutionSettings { Think = thinkValue };

// Act
await sut.GetTextContentsAsync("Any prompt", settings);

// Assert
var requestPayload = JsonSerializer.Deserialize<GenerateRequest>(this._messageHandlerStub.RequestContent);
Assert.NotNull(requestPayload);
Assert.Equal(thinkValue, (bool?)requestPayload.Think);
}

[Fact]
public async Task GetTextContentsShouldNotSendThinkWhenNotSetAsync()
{
// Arrange
var sut = new OllamaTextGenerationService("fake-model", httpClient: this._httpClient);

// Act
await sut.GetTextContentsAsync("Any prompt");

// Assert
var requestPayload = JsonSerializer.Deserialize<GenerateRequest>(this._messageHandlerStub.RequestContent);
Assert.NotNull(requestPayload);
Assert.Null(requestPayload.Think);
}

[Theory]
[InlineData(true)]
[InlineData(false)]
public async Task GetStreamingTextContentsShouldSendThinkSettingAsync(bool thinkValue)
{
// Arrange
var sut = new OllamaTextGenerationService("fake-model", httpClient: this._httpClient);
var settings = new OllamaPromptExecutionSettings { Think = thinkValue };

// Act
await sut.GetStreamingTextContentsAsync("Any prompt", settings).GetAsyncEnumerator().MoveNextAsync();

// Assert
var requestPayload = JsonSerializer.Deserialize<GenerateRequest>(this._messageHandlerStub.RequestContent);
Assert.NotNull(requestPayload);
Assert.Equal(thinkValue, (bool?)requestPayload.Think);
}

/// <summary>
/// Disposes resources used by this class.
/// </summary>
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -41,6 +41,7 @@ public void FromExecutionSettingsWhenNullShouldReturnDefault()
Assert.Null(ollamaExecutionSettings.Temperature);
Assert.Null(ollamaExecutionSettings.TopP);
Assert.Null(ollamaExecutionSettings.TopK);
Assert.Null(ollamaExecutionSettings.Think);
}

[Fact]
Expand Down Expand Up @@ -187,6 +188,45 @@ public void ClonePreservesServiceId()
Assert.Equal(testSettings.Temperature, cloned.Temperature);
}

[Theory]
[InlineData(true)]
[InlineData(false)]
public void ThinkPropertyRoundTripsViaSerialization(bool thinkValue)
{
// Arrange
string jsonSettings = $$"""{ "think": {{thinkValue.ToString().ToLowerInvariant()}} }""";

// Act
var executionSettings = JsonSerializer.Deserialize<OllamaPromptExecutionSettings>(jsonSettings);

// Assert
Assert.Equal(thinkValue, executionSettings!.Think);
}

[Fact]
public void ThinkPropertyIsPreservedByClone()
{
// Arrange
var settings = new OllamaPromptExecutionSettings { Think = false };

// Act
var clone = (OllamaPromptExecutionSettings)settings.Clone();

// Assert
Assert.Equal(false, clone.Think);
}

[Fact]
public void ThinkPropertyThrowsWhenFrozen()
{
// Arrange
var settings = new OllamaPromptExecutionSettings();
settings.Freeze();

// Act & Assert
Assert.Throws<InvalidOperationException>(() => settings.Think = true);
}

[Fact]
public void PromptExecutionSettingsFreezeWorksAsExpected()
{
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -148,7 +148,8 @@ private static GenerateRequest CreateRequest(OllamaPromptExecutionSettings setti
NumPredict = settings.NumPredict
},
Model = selectedModel,
Stream = true
Stream = true,
Think = settings.Think.HasValue ? (OllamaSharp.Models.Chat.ThinkValue?)settings.Think.Value : null
};
Comment thread
arashzjahangiri marked this conversation as resolved.

return request;
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -131,6 +131,30 @@ public int? NumPredict
}
}

/// <summary>
/// Enables or disables thinking for reasoning models such as deepseek-r1, qwen3, and phi4-reasoning.
/// Set to <c>false</c> to disable thinking and receive a standard response when using a model that
/// enables thinking by default. Set to <c>true</c> to explicitly enable thinking.
/// When <c>null</c> (the default), the model's own default behavior is used.
/// </summary>
/// <remarks>
/// When thinking is active, the model's reasoning output lands in a separate thinking stream
/// rather than in the main response content. Setting this to <c>false</c> suppresses thinking
/// so that all output appears in the standard response field.
/// </remarks>
[JsonPropertyName("think")]
[JsonIgnore(Condition = JsonIgnoreCondition.WhenWritingNull)]
public bool? Think
{
get => this._think;

set
{
this.ThrowIfFrozen();
this._think = value;
}
}

/// <inheritdoc/>
public override void Freeze()
{
Expand Down Expand Up @@ -161,6 +185,7 @@ public override PromptExecutionSettings Clone()
NumPredict = this.NumPredict,
Stop = this.Stop is not null ? new List<string>(this.Stop) : null,
FunctionChoiceBehavior = this.FunctionChoiceBehavior,
Think = this.Think,
};
}

Expand All @@ -171,6 +196,7 @@ public override PromptExecutionSettings Clone()
private float? _topP;
private int? _topK;
private int? _numPredict;
private bool? _think;

#endregion
}
Loading