diff --git a/dotnet/src/Connectors/Connectors.MistralAI.UnitTests/MistralAIPromptExecutionSettingsTests.cs b/dotnet/src/Connectors/Connectors.MistralAI.UnitTests/MistralAIPromptExecutionSettingsTests.cs index 4422740da6c8..8a4b3c31594d 100644 --- a/dotnet/src/Connectors/Connectors.MistralAI.UnitTests/MistralAIPromptExecutionSettingsTests.cs +++ b/dotnet/src/Connectors/Connectors.MistralAI.UnitTests/MistralAIPromptExecutionSettingsTests.cs @@ -1,5 +1,6 @@ // Copyright (c) Microsoft. All rights reserved. +using System; using System.Text.Json; using Microsoft.SemanticKernel; using Microsoft.SemanticKernel.Connectors.MistralAI; @@ -68,4 +69,44 @@ public void FromExecutionSettingsWhenSerializedHasPropertiesShouldPopulateSpecia Assert.True(MistralExecutionSettings.SafePrompt); Assert.Equal(123, MistralExecutionSettings.RandomSeed); } + + [Fact] + public void FreezeShouldPreventPropertyModification() + { + // Arrange + var settings = new MistralAIPromptExecutionSettings + { + Temperature = 0.7, + TopP = 1, + MaxTokens = 100, + SafePrompt = false, + Stop = ["foo", "bar"] + }; + + // Act + settings.Freeze(); + + // Assert + // Try to modify a property after freezing + Assert.Throws(() => settings.Temperature = 0.8); + Assert.Throws(() => settings.TopP = 0.9); + Assert.Throws(() => settings.MaxTokens = 50); + Assert.Throws(() => settings.SafePrompt = true); + Assert.Throws(() => settings.Stop.Add("baz")); + } + + [Fact] + public void FreezeShouldNotAllowMultipleFreezes() + { + // Arrange + var settings = new MistralAIPromptExecutionSettings(); + settings.Freeze(); // First freeze + + // Act + settings.Freeze(); // Second freeze (should not throw) + + // Assert + // No exception should be thrown + Assert.True(settings.IsFrozen); // Assuming IsFrozen is a property indicating the freeze state + } } diff --git a/dotnet/src/Connectors/Connectors.MistralAI/Client/ContentChunkType.cs b/dotnet/src/Connectors/Connectors.MistralAI/Client/ContentChunkType.cs index 1ed890d35b38..95125f23f191 100644 --- a/dotnet/src/Connectors/Connectors.MistralAI/Client/ContentChunkType.cs +++ b/dotnet/src/Connectors/Connectors.MistralAI/Client/ContentChunkType.cs @@ -43,7 +43,7 @@ public ContentChunkType(string type) /// the second instance to compare /// false if left and right are both null or have equivalent labels; true otherwise public static bool operator !=(ContentChunkType left, ContentChunkType right) - => !(left == right); + => !left.Equals(right); /// public override bool Equals([NotNullWhen(true)] object? obj) diff --git a/dotnet/src/Connectors/Connectors.MistralAI/MistralAIPromptExecutionSettings.cs b/dotnet/src/Connectors/Connectors.MistralAI/MistralAIPromptExecutionSettings.cs index 7a43d96b47bd..5ea83a482756 100644 --- a/dotnet/src/Connectors/Connectors.MistralAI/MistralAIPromptExecutionSettings.cs +++ b/dotnet/src/Connectors/Connectors.MistralAI/MistralAIPromptExecutionSettings.cs @@ -1,6 +1,7 @@ // Copyright (c) Microsoft. All rights reserved. using System.Collections.Generic; +using System.Collections.ObjectModel; using System.Text.Json; using System.Text.Json.Serialization; using Microsoft.SemanticKernel.ChatCompletion; @@ -247,6 +248,11 @@ public override void Freeze() return; } + if (this._stop is not null) + { + this._stop = new ReadOnlyCollection(this._stop); + } + base.Freeze(); } @@ -267,7 +273,7 @@ public override PromptExecutionSettings Clone() ResponseFormat = this.ResponseFormat, FrequencyPenalty = this.FrequencyPenalty, PresencePenalty = this.PresencePenalty, - Stop = this.Stop, + Stop = this.Stop is not null ? new List(this.Stop) : null, }; }