.Net: Added AzureChatExtensionsOptions property and deprecated WithData classes (#6454)

### Motivation and Context

<!-- Thank you for your contribution to the semantic-kernel repo!
Please help reviewers and future users, providing the following
information:
  1. Why is this change required?
  2. What problem does it solve?
  3. What scenario does it contribute to?
  4. If it fixes an open issue, please link to the issue here.
-->

Fixes: https://github.com/microsoft/semantic-kernel/issues/4787
Fixes: https://github.com/microsoft/semantic-kernel/issues/6061
Fixes: https://github.com/microsoft/semantic-kernel/issues/6448
Fixes: https://github.com/microsoft/semantic-kernel/issues/6112

Discussion:
https://github.com/microsoft/semantic-kernel/discussions/6016#discussioncomment-9459380

There are two reasons why this change is required:
1. Azure .NET SDK supports `chat completion on your data` functionality
out-of-the-box, which means that now we don't need custom
implementation.
2. `Chat completion on your data` new API has [breaking
changes](https://learn.microsoft.com/en-us/azure/ai-services/openai/references/on-your-data),
which makes current `WithData` classes non-functional.

### Description

<!-- Describe your changes, the overall approach, the underlying design.
These notes will help understanding how your code works. Thanks! -->

1. `AzureChatExtensionsOptions` property was added to
`OpenAIPromptExecutionSettings`. Initial idea was to add it on
`AzureOpenAIChatCompletionService` class level (in all constructors and
extension methods), but it looks like this configuration contains some
properties which should be useful per request (e.g. index name, search
filter etc). Later, we can also add it on service class level, if needed
(although I would do that when Options classes for all
`AddChatCompletion...` extension methods will be introduced, to avoid
more parameters in these methods at the moment).
2. `AzureChatExtensionsOptions` property is marked with `JsonIgnore`
attribute, because it's still needs to be investigated if this
configuration is serializable. It supports not only Azure AI Search
configuration, but also [other
configurations](https://learn.microsoft.com/en-us/azure/ai-services/openai/references/on-your-data#data-source)
like Azure Cosmos DB for MongoDB, Pinecone etc. We can release it
without JSON serialization first, to unblock code-first customers, and
we can add support for JSON serialization later (i.e. `config.json`
files), if there will be such request.

Note: It looks like `OpenAIPromptExecutionSettings` is not ideal place
for Azure-specific `AzureChatExtensionsOptions` property. I was thinking
to add derived `AzureOpenAIPromptExecutionSettings :
OpenAIPromptExecutionSettings` class (and unmark
`OpenAIPromptExecutionSettings` as sealed), but this looks like some
scope of work which should be implemented when OpenAI and Azure OpenAI
functionality will be separated by SDKs.

### Contribution Checklist

<!-- Before submitting this PR, please make sure: -->

- [x] The code builds clean without any errors or warnings
- [x] The PR follows the [SK Contribution
Guidelines](https://github.com/microsoft/semantic-kernel/blob/main/CONTRIBUTING.md)
and the [pre-submission formatting
script](https://github.com/microsoft/semantic-kernel/blob/main/CONTRIBUTING.md#development-scripts)
raises no violations
- [x] All unit tests pass, and I have added new tests where possible
- [x] I didn't break anyone 😄
This commit is contained in:
Dmytro Struk
2024-06-03 14:28:28 +00:00
committed by GitHub
parent fb8edbef94
commit 060699cc8f
20 changed files with 110 additions and 29 deletions
+1 -1
View File
@@ -81,7 +81,7 @@ jobs:
run: |
export UT_PROJECTS=$(find ./dotnet -type f -name "*.UnitTests.csproj" | grep -v -E "(Experimental.Orchestration.Flow.UnitTests.csproj|Experimental.Assistants.UnitTests.csproj)" | tr '\n' ' ')
for project in $UT_PROJECTS; do
dotnet test -c ${{ matrix.configuration }} $project --no-build -v Normal --logger trx --collect:"XPlat Code Coverage" --results-directory:"TestResults/Coverage/" -- DataCollectionRunSettings.DataCollectors.DataCollector.Configuration.ExcludeByAttribute=ObsoleteAttribute,GeneratedCodeAttribute,CompilerGeneratedAttribute,ExcludeFromCodeCoverageAttribute
dotnet test -c ${{ matrix.configuration }} $project --no-build -v Normal --logger trx --collect:"XPlat Code Coverage" --results-directory:"TestResults/Coverage/" -- DataCollectionRunSettings.DataCollectors.DataCollector.Configuration.ExcludeByAttribute=GeneratedCodeAttribute,CompilerGeneratedAttribute,ExcludeFromCodeCoverageAttribute
done
- name: Run Integration Tests
+1 -1
View File
@@ -27,7 +27,7 @@ foreach ($project in $testProjects) {
dotnet test $testProjectPath `
--collect:"XPlat Code Coverage" `
--results-directory:$coverageOutputPath `
-- DataCollectionRunSettings.DataCollectors.DataCollector.Configuration.ExcludeByAttribute=ObsoleteAttribute,GeneratedCodeAttribute,CompilerGeneratedAttribute,ExcludeFromCodeCoverageAttribute `
-- DataCollectionRunSettings.DataCollectors.DataCollector.Configuration.ExcludeByAttribute=GeneratedCodeAttribute,CompilerGeneratedAttribute,ExcludeFromCodeCoverageAttribute `
}
@@ -1,5 +1,6 @@
// Copyright (c) Microsoft. All rights reserved.
using Azure.AI.OpenAI;
using Microsoft.SemanticKernel;
using Microsoft.SemanticKernel.ChatCompletion;
using Microsoft.SemanticKernel.Connectors.OpenAI;
@@ -32,7 +33,13 @@ public class AzureOpenAIWithData_ChatCompletion(ITestOutputHelper output) : Base
{
Console.WriteLine("=== Example with Chat Completion ===");
var chatCompletion = new AzureOpenAIChatCompletionWithDataService(GetCompletionWithDataConfig());
var kernel = Kernel.CreateBuilder()
.AddAzureOpenAIChatCompletion(
TestConfiguration.AzureOpenAI.ChatDeploymentName,
TestConfiguration.AzureOpenAI.Endpoint,
TestConfiguration.AzureOpenAI.ApiKey)
.Build();
var chatHistory = new ChatHistory();
// First question without previous context based on uploaded content.
@@ -40,10 +47,14 @@ public class AzureOpenAIWithData_ChatCompletion(ITestOutputHelper output) : Base
chatHistory.AddUserMessage(ask);
// Chat Completion example
var chatMessage = (AzureOpenAIWithDataChatMessageContent)await chatCompletion.GetChatMessageContentAsync(chatHistory);
var chatExtensionsOptions = GetAzureChatExtensionsOptions();
var promptExecutionSettings = new OpenAIPromptExecutionSettings { AzureChatExtensionsOptions = chatExtensionsOptions };
var chatCompletion = kernel.GetRequiredService<IChatCompletionService>();
var chatMessage = await chatCompletion.GetChatMessageContentAsync(chatHistory, promptExecutionSettings);
var response = chatMessage.Content!;
var toolResponse = chatMessage.ToolContent;
// Output
// Ask: How did Emily and David meet?
@@ -53,11 +64,6 @@ public class AzureOpenAIWithData_ChatCompletion(ITestOutputHelper output) : Base
Console.WriteLine();
// Chat history maintenance
if (!string.IsNullOrEmpty(toolResponse))
{
chatHistory.AddMessage(AuthorRole.Tool, toolResponse);
}
chatHistory.AddAssistantMessage(response);
// Second question based on uploaded content.
@@ -68,7 +74,7 @@ public class AzureOpenAIWithData_ChatCompletion(ITestOutputHelper output) : Base
Console.WriteLine($"Ask: {ask}");
Console.WriteLine("Response: ");
await foreach (var word in chatCompletion.GetStreamingChatMessageContentsAsync(chatHistory))
await foreach (var word in chatCompletion.GetStreamingChatMessageContentsAsync(chatHistory, promptExecutionSettings))
{
Console.Write(word);
}
@@ -83,16 +89,20 @@ public class AzureOpenAIWithData_ChatCompletion(ITestOutputHelper output) : Base
var ask = "How did Emily and David meet?";
var completionWithDataConfig = GetCompletionWithDataConfig();
Kernel kernel = Kernel.CreateBuilder()
.AddAzureOpenAIChatCompletion(config: completionWithDataConfig)
var kernel = Kernel.CreateBuilder()
.AddAzureOpenAIChatCompletion(
TestConfiguration.AzureOpenAI.ChatDeploymentName,
TestConfiguration.AzureOpenAI.Endpoint,
TestConfiguration.AzureOpenAI.ApiKey)
.Build();
var function = kernel.CreateFunctionFromPrompt("Question: {{$input}}");
var chatExtensionsOptions = GetAzureChatExtensionsOptions();
var promptExecutionSettings = new OpenAIPromptExecutionSettings { AzureChatExtensionsOptions = chatExtensionsOptions };
// First question without previous context based on uploaded content.
var response = await kernel.InvokeAsync(function, new() { ["input"] = ask });
var response = await kernel.InvokeAsync(function, new(promptExecutionSettings) { ["input"] = ask });
// Output
// Ask: How did Emily and David meet?
@@ -103,7 +113,7 @@ public class AzureOpenAIWithData_ChatCompletion(ITestOutputHelper output) : Base
// Second question based on uploaded content.
ask = "What are Emily and David studying?";
response = await kernel.InvokeAsync(function, new() { ["input"] = ask });
response = await kernel.InvokeAsync(function, new(promptExecutionSettings) { ["input"] = ask });
// Output
// Ask: What are Emily and David studying?
@@ -117,16 +127,18 @@ public class AzureOpenAIWithData_ChatCompletion(ITestOutputHelper output) : Base
/// <summary>
/// Initializes a new instance of the <see cref="AzureOpenAIChatCompletionWithDataConfig"/> class.
/// </summary>
private static AzureOpenAIChatCompletionWithDataConfig GetCompletionWithDataConfig()
private static AzureChatExtensionsOptions GetAzureChatExtensionsOptions()
{
return new AzureOpenAIChatCompletionWithDataConfig
var azureSearchExtensionConfiguration = new AzureSearchChatExtensionConfiguration
{
CompletionModelId = TestConfiguration.AzureOpenAI.ChatDeploymentName,
CompletionEndpoint = TestConfiguration.AzureOpenAI.Endpoint,
CompletionApiKey = TestConfiguration.AzureOpenAI.ApiKey,
DataSourceEndpoint = TestConfiguration.AzureAISearch.Endpoint,
DataSourceApiKey = TestConfiguration.AzureAISearch.ApiKey,
DataSourceIndex = TestConfiguration.AzureAISearch.IndexName
SearchEndpoint = new Uri(TestConfiguration.AzureAISearch.Endpoint),
Authentication = new OnYourDataApiKeyAuthenticationOptions(TestConfiguration.AzureAISearch.ApiKey),
IndexName = TestConfiguration.AzureAISearch.IndexName
};
return new AzureChatExtensionsOptions
{
Extensions = { azureSearchExtensionConfiguration }
};
}
}
@@ -12,6 +12,7 @@ namespace Microsoft.SemanticKernel.Connectors.OpenAI;
/// OpenAI specialized with data chat message content
/// </summary>
[Experimental("SKEXP0010")]
[Obsolete("This class is deprecated in favor of OpenAIPromptExecutionSettings.AzureChatExtensionsOptions")]
public sealed class AzureOpenAIWithDataChatMessageContent : ChatMessageContent
{
/// <summary>
@@ -16,6 +16,7 @@ namespace Microsoft.SemanticKernel.Connectors.OpenAI;
/// Represents a chat message content chunk that was streamed from the remote model.
/// </remarks>
[Experimental("SKEXP0010")]
[Obsolete("This class is deprecated in favor of OpenAIPromptExecutionSettings.AzureChatExtensionsOptions")]
public sealed class AzureOpenAIWithDataStreamingChatMessageContent : StreamingChatMessageContent
{
/// <inheritdoc/>
@@ -1107,7 +1107,8 @@ internal abstract class ClientCore
Seed = executionSettings.Seed,
User = executionSettings.User,
LogProbabilitiesPerToken = executionSettings.TopLogprobs,
EnableLogProbabilities = executionSettings.Logprobs
EnableLogProbabilities = executionSettings.Logprobs,
AzureExtensionsOptions = executionSettings.AzureChatExtensionsOptions
};
switch (executionSettings.ResponseFormat)
@@ -1,5 +1,6 @@
// Copyright (c) Microsoft. All rights reserved.
using System;
using System.Diagnostics.CodeAnalysis;
namespace Microsoft.SemanticKernel.Connectors.OpenAI;
@@ -9,6 +10,7 @@ namespace Microsoft.SemanticKernel.Connectors.OpenAI;
/// More information: <see href="https://learn.microsoft.com/en-us/azure/ai-services/openai/use-your-data-quickstart"/>
/// </summary>
[Experimental("SKEXP0010")]
[Obsolete("This class is deprecated in favor of OpenAIPromptExecutionSettings.AzureChatExtensionsOptions")]
public class AzureOpenAIChatCompletionWithDataConfig
{
/// <summary>
@@ -27,6 +27,7 @@ namespace Microsoft.SemanticKernel.Connectors.OpenAI;
/// More information: <see href="https://learn.microsoft.com/en-us/azure/ai-services/openai/use-your-data-quickstart"/>
/// </summary>
[Experimental("SKEXP0010")]
[Obsolete("This class is deprecated in favor of OpenAIPromptExecutionSettings.AzureChatExtensionsOptions")]
public sealed class AzureOpenAIChatCompletionWithDataService : IChatCompletionService, ITextGenerationService
{
/// <summary>
@@ -1,11 +1,13 @@
// Copyright (c) Microsoft. All rights reserved.
using System;
using System.Diagnostics.CodeAnalysis;
using System.Text.Json.Serialization;
namespace Microsoft.SemanticKernel.Connectors.OpenAI;
[Experimental("SKEXP0010")]
[Obsolete("This class is deprecated in favor of OpenAIPromptExecutionSettings.AzureChatExtensionsOptions")]
internal sealed class ChatWithDataMessage
{
[JsonPropertyName("role")]
@@ -8,6 +8,7 @@ using System.Text.Json.Serialization;
namespace Microsoft.SemanticKernel.Connectors.OpenAI;
[Experimental("SKEXP0010")]
[Obsolete("This class is deprecated in favor of OpenAIPromptExecutionSettings.AzureChatExtensionsOptions")]
internal sealed class ChatWithDataRequest
{
[JsonPropertyName("temperature")]
@@ -42,6 +43,7 @@ internal sealed class ChatWithDataRequest
}
[Experimental("SKEXP0010")]
[Obsolete("This class is deprecated in favor of OpenAIPromptExecutionSettings.AzureChatExtensionsOptions")]
internal sealed class ChatWithDataSource
{
[JsonPropertyName("type")]
@@ -55,6 +57,7 @@ internal sealed class ChatWithDataSource
}
[Experimental("SKEXP0010")]
[Obsolete("This class is deprecated in favor of OpenAIPromptExecutionSettings.AzureChatExtensionsOptions")]
internal sealed class ChatWithDataSourceParameters
{
[JsonPropertyName("endpoint")]
@@ -10,6 +10,7 @@ namespace Microsoft.SemanticKernel.Connectors.OpenAI;
#pragma warning disable CA1812 // Avoid uninstantiated internal classes
[Experimental("SKEXP0010")]
[Obsolete("This class is deprecated in favor of OpenAIPromptExecutionSettings.AzureChatExtensionsOptions")]
[method: JsonConstructor]
internal sealed class ChatWithDataResponse(ChatWithDataUsage usage)
{
@@ -33,6 +34,7 @@ internal sealed class ChatWithDataResponse(ChatWithDataUsage usage)
}
[Experimental("SKEXP0010")]
[Obsolete("This class is deprecated in favor of OpenAIPromptExecutionSettings.AzureChatExtensionsOptions")]
[SuppressMessage("Performance", "CA1812:Avoid uninstantiated internal classes", Justification = "Used for JSON deserialization")]
internal sealed class ChatWithDataChoice
{
@@ -41,6 +43,7 @@ internal sealed class ChatWithDataChoice
}
[Experimental("SKEXP0010")]
[Obsolete("This class is deprecated in favor of OpenAIPromptExecutionSettings.AzureChatExtensionsOptions")]
internal sealed class ChatWithDataUsage
{
[JsonPropertyName("prompt_tokens")]
@@ -8,6 +8,7 @@ using System.Text.Json.Serialization;
namespace Microsoft.SemanticKernel.Connectors.OpenAI;
[Experimental("SKEXP0010")]
[Obsolete("This class is deprecated in favor of OpenAIPromptExecutionSettings.AzureChatExtensionsOptions")]
[SuppressMessage("Performance", "CA1812:Avoid uninstantiated internal classes", Justification = "Used for JSON deserialization")]
internal sealed class ChatWithDataStreamingResponse
{
@@ -28,6 +29,7 @@ internal sealed class ChatWithDataStreamingResponse
}
[Experimental("SKEXP0010")]
[Obsolete("This class is deprecated in favor of OpenAIPromptExecutionSettings.AzureChatExtensionsOptions")]
[SuppressMessage("Performance", "CA1812:Avoid uninstantiated internal classes", Justification = "Used for JSON deserialization")]
internal sealed class ChatWithDataStreamingChoice
{
@@ -39,6 +41,7 @@ internal sealed class ChatWithDataStreamingChoice
}
[Experimental("SKEXP0010")]
[Obsolete("This class is deprecated in favor of OpenAIPromptExecutionSettings.AzureChatExtensionsOptions")]
[SuppressMessage("Performance", "CA1812:Avoid uninstantiated internal classes", Justification = "Used for JSON deserialization")]
internal sealed class ChatWithDataStreamingMessage
{
@@ -50,6 +53,7 @@ internal sealed class ChatWithDataStreamingMessage
}
[Experimental("SKEXP0010")]
[Obsolete("This class is deprecated in favor of OpenAIPromptExecutionSettings.AzureChatExtensionsOptions")]
internal sealed class ChatWithDataStreamingDelta
{
[JsonPropertyName("role")]
@@ -287,6 +287,23 @@ public sealed class OpenAIPromptExecutionSettings : PromptExecutionSettings
}
}
/// <summary>
/// An abstraction of additional settings for chat completion, see https://learn.microsoft.com/en-us/dotnet/api/azure.ai.openai.azurechatextensionsoptions.
/// This property is compatible only with Azure OpenAI.
/// </summary>
[Experimental("SKEXP0010")]
[JsonIgnore]
public AzureChatExtensionsOptions? AzureChatExtensionsOptions
{
get => this._azureChatExtensionsOptions;
set
{
this.ThrowIfFrozen();
this._azureChatExtensionsOptions = value;
}
}
/// <inheritdoc/>
public override void Freeze()
{
@@ -329,7 +346,8 @@ public sealed class OpenAIPromptExecutionSettings : PromptExecutionSettings
User = this.User,
ChatSystemPrompt = this.ChatSystemPrompt,
Logprobs = this.Logprobs,
TopLogprobs = this.TopLogprobs
TopLogprobs = this.TopLogprobs,
AzureChatExtensionsOptions = this.AzureChatExtensionsOptions,
};
}
@@ -376,6 +394,7 @@ public sealed class OpenAIPromptExecutionSettings : PromptExecutionSettings
/// <param name="executionSettings">Template configuration</param>
/// <param name="defaultMaxTokens">Default max tokens</param>
/// <returns>An instance of OpenAIPromptExecutionSettings</returns>
[Obsolete("This method is deprecated in favor of OpenAIPromptExecutionSettings.AzureChatExtensionsOptions")]
public static OpenAIPromptExecutionSettings FromExecutionSettingsWithData(PromptExecutionSettings? executionSettings, int? defaultMaxTokens = null)
{
var settings = FromExecutionSettings(executionSettings, defaultMaxTokens);
@@ -407,6 +426,7 @@ public sealed class OpenAIPromptExecutionSettings : PromptExecutionSettings
private string? _chatSystemPrompt;
private bool? _logprobs;
private int? _topLogprobs;
private AzureChatExtensionsOptions? _azureChatExtensionsOptions;
#endregion
}
@@ -906,6 +906,7 @@ public static class OpenAIServiceCollectionExtensions
/// More information: <see href="https://learn.microsoft.com/en-us/azure/ai-services/openai/use-your-data-quickstart"/>
/// </remarks>
[Experimental("SKEXP0010")]
[Obsolete("This method is deprecated in favor of OpenAIPromptExecutionSettings.AzureChatExtensionsOptions")]
public static IKernelBuilder AddAzureOpenAIChatCompletion(
this IKernelBuilder builder,
AzureOpenAIChatCompletionWithDataConfig config,
@@ -936,6 +937,7 @@ public static class OpenAIServiceCollectionExtensions
/// More information: <see href="https://learn.microsoft.com/en-us/azure/ai-services/openai/use-your-data-quickstart"/>
/// </remarks>
[Experimental("SKEXP0010")]
[Obsolete("This method is deprecated in favor of OpenAIPromptExecutionSettings.AzureChatExtensionsOptions")]
public static IServiceCollection AddAzureOpenAIChatCompletion(
this IServiceCollection services,
AzureOpenAIChatCompletionWithDataConfig config,
@@ -9,6 +9,8 @@ using Xunit;
namespace SemanticKernel.Connectors.UnitTests.OpenAI.AzureSdk;
#pragma warning disable CS0618 // AzureOpenAIChatCompletionWithData is deprecated in favor of OpenAIPromptExecutionSettings.AzureChatExtensionsOptions
/// <summary>
/// Unit tests for <see cref="AzureOpenAIWithDataChatMessageContent"/> class.
/// </summary>
@@ -6,6 +6,8 @@ using Xunit;
namespace SemanticKernel.Connectors.UnitTests.OpenAI.AzureSdk;
#pragma warning disable CS0618 // AzureOpenAIChatCompletionWithData is deprecated in favor of OpenAIPromptExecutionSettings.AzureChatExtensionsOptions
/// <summary>
/// Unit tests for <see cref="AzureOpenAIWithDataStreamingChatMessageContent"/> class.
/// </summary>
@@ -163,7 +163,18 @@ public sealed class AzureOpenAIChatCompletionServiceTests : IDisposable
TokenSelectionBiases = new Dictionary<int, int> { { 2, 3 } },
StopSequences = ["stop_sequence"],
Logprobs = true,
TopLogprobs = 5
TopLogprobs = 5,
AzureChatExtensionsOptions = new AzureChatExtensionsOptions
{
Extensions =
{
new AzureSearchChatExtensionConfiguration
{
SearchEndpoint = new Uri("http://test-search-endpoint"),
IndexName = "test-index-name"
}
}
}
};
var chatHistory = new ChatHistory();
@@ -222,6 +233,14 @@ public sealed class AzureOpenAIChatCompletionServiceTests : IDisposable
Assert.Equal("stop_sequence", content.GetProperty("stop")[0].GetString());
Assert.True(content.GetProperty("logprobs").GetBoolean());
Assert.Equal(5, content.GetProperty("top_logprobs").GetInt32());
var dataSources = content.GetProperty("data_sources");
Assert.Equal(1, dataSources.GetArrayLength());
Assert.Equal("azure_search", dataSources[0].GetProperty("type").GetString());
var dataSourceParameters = dataSources[0].GetProperty("parameters");
Assert.Equal("http://test-search-endpoint/", dataSourceParameters.GetProperty("endpoint").GetString());
Assert.Equal("test-index-name", dataSourceParameters.GetProperty("index_name").GetString());
}
[Theory]
@@ -13,6 +13,8 @@ using Xunit;
namespace SemanticKernel.Connectors.UnitTests.OpenAI.ChatCompletionWithData;
#pragma warning disable CS0618 // AzureOpenAIChatCompletionWithData is deprecated in favor of OpenAIPromptExecutionSettings.AzureChatExtensionsOptions
/// <summary>
/// Unit tests for <see cref="AzureOpenAIChatCompletionWithDataService"/>
/// </summary>
@@ -32,6 +32,7 @@ public class OpenAIPromptExecutionSettingsTests
Assert.Null(executionSettings.TokenSelectionBiases);
Assert.Null(executionSettings.TopLogprobs);
Assert.Null(executionSettings.Logprobs);
Assert.Null(executionSettings.AzureChatExtensionsOptions);
Assert.Equal(128, executionSettings.MaxTokens);
}
@@ -248,8 +249,9 @@ public class OpenAIPromptExecutionSettingsTests
var executionSettings = new OpenAIPromptExecutionSettings { StopSequences = [] };
// Act
#pragma warning disable CS0618 // AzureOpenAIChatCompletionWithData is deprecated in favor of OpenAIPromptExecutionSettings.AzureChatExtensionsOptions
var executionSettingsWithData = OpenAIPromptExecutionSettings.FromExecutionSettingsWithData(executionSettings);
#pragma warning restore CS0618
// Assert
Assert.Null(executionSettingsWithData.StopSequences);
}
@@ -17,6 +17,8 @@ using Xunit;
namespace SemanticKernel.Connectors.UnitTests.OpenAI;
#pragma warning disable CS0618 // AzureOpenAIChatCompletionWithData is deprecated in favor of OpenAIPromptExecutionSettings.AzureChatExtensionsOptions
/// <summary>
/// Unit tests for <see cref="OpenAIServiceCollectionExtensions"/> class.
/// </summary>