diff --git a/.vscode/cspell.json b/.vscode/cspell.json index 5ae22094a0d3..cf37ff5c2057 100644 --- a/.vscode/cspell.json +++ b/.vscode/cspell.json @@ -34,6 +34,7 @@ "*.user", ".vscode/cspell.json", "assets.json", + "eng/Packages.Data.props", "sdk/confidentialledger/Azure.Security.CodeTransparency/tests/TestFiles/*", // These services are opted out of public API surface spell checking. // Spelling issues must be addressed before adding these back in. @@ -48,6 +49,7 @@ "sdk/modelsrepository/*/api/*.cs", "sdk/monitor/Azure.ResourceManager.Monitor/api/*.cs", "sdk/objectanchors/*/api/*.cs", + "sdk/openai/Azure.AI.OpenAI/tests/Assets/playback_test_config.json", "sdk/purview/*/api/*.cs", "sdk/remoterendering/*/api/*.cs", "sdk/videoanalyzer/*/api/*.cs", @@ -975,6 +977,25 @@ "ipfix" ] }, + { + "filename": "**/sdk/openai/**/*", + "words": [ + "AOAI", + "Arrr", + "Dall", + "Dalle", + "Dall-E", + "devcert", + "Filip", + "Filip's", + "granularities", + "haikus", + "msdocs", + "OpenAI", + "Pavleski", + "Tekakwitha" + ] + }, { "filename": "**/sdk/operationalinsights/**/*.cs", "words": [ diff --git a/eng/Packages.Data.props b/eng/Packages.Data.props index 1395d0b59b9c..bfa73b61bdca 100644 --- a/eng/Packages.Data.props +++ b/eng/Packages.Data.props @@ -86,7 +86,7 @@ - + @@ -157,7 +157,7 @@ @@ -179,7 +179,7 @@ - + - + diff --git a/sdk/openai/Azure.AI.OpenAI/README.md b/sdk/openai/Azure.AI.OpenAI/README.md index 703467a165ad..c1ac19120c87 100644 --- a/sdk/openai/Azure.AI.OpenAI/README.md +++ b/sdk/openai/Azure.AI.OpenAI/README.md @@ -157,7 +157,7 @@ ChatCompletion completion = chatClient.CompleteChat( [ // System messages represent instructions or other guidance about how the assistant should behave new SystemChatMessage("You are a helpful assistant that talks like a pirate."), - // User messages represent user input, whether historical or the most recen tinput + // User messages represent user input, whether historical or the most recent input new UserChatMessage("Hi, can you help me?"), // Assistant messages in a request represent conversation history for responses new AssistantChatMessage("Arrr! Of course, me hearty! What can I do for ye?"), @@ -362,7 +362,9 @@ foreach (KeyValuePair indexToIdPair in toolCallIdsByIndex) functionArgumentBuildersByIndex[indexToIdPair.Key].ToString())); } -conversationMessages.Add(new AssistantChatMessage(toolCalls, contentBuilder.ToString())); +var assistantChatMessage = new AssistantChatMessage(toolCalls); +assistantChatMessage.Content.Add(ChatMessageContentPart.CreateTextPart(contentBuilder.ToString())); +conversationMessages.Add(assistantChatMessage); // Placeholder: each tool call must be resolved, like in the non-streaming case string GetToolCallOutput(ChatToolCall toolCall) => null; @@ -526,11 +528,11 @@ This project has adopted the [Microsoft Open Source Code of Conduct][code_of_con [azure_openai_client_class]: https://github.com/Azure/azure-sdk-for-net/blob/main/sdk/openai/Azure.AI.OpenAI/src/Custom/AzureOpenAIClient.cs [openai_rest]: https://learn.microsoft.com/azure/cognitive-services/openai/reference [azure_openai_completions_docs]: https://learn.microsoft.com/azure/cognitive-services/openai/how-to/completions -[azure_openai_embeddgings_docs]: https://learn.microsoft.com/azure/cognitive-services/openai/concepts/understand-embeddings +[azure_openai_embeddings_docs]: https://learn.microsoft.com/azure/cognitive-services/openai/concepts/understand-embeddings [openai_contrib]: https://github.com/Azure/azure-sdk-for-net/blob/main/CONTRIBUTING.md [cla]: https://cla.microsoft.com [code_of_conduct]: https://opensource.microsoft.com/codeofconduct/ [code_of_conduct_faq]: https://opensource.microsoft.com/codeofconduct/faq/ [email_opencode]: mailto:opencode@microsoft.com -![Impressions](https://azure-sdk-impressions.azurewebsites.net/api/impressions/azure-sdk-for-net/sdk/openai/Azure.AI.OpenAI/README.png) \ No newline at end of file +![Impressions](https://azure-sdk-impressions.azurewebsites.net/api/impressions/azure-sdk-for-net/sdk/openai/Azure.AI.OpenAI/README.png) diff --git a/sdk/openai/Azure.AI.OpenAI/api/Azure.AI.OpenAI.netstandard2.0.cs b/sdk/openai/Azure.AI.OpenAI/api/Azure.AI.OpenAI.netstandard2.0.cs index 2a47a4534fee..d1ecd92f305a 100644 --- a/sdk/openai/Azure.AI.OpenAI/api/Azure.AI.OpenAI.netstandard2.0.cs +++ b/sdk/openai/Azure.AI.OpenAI/api/Azure.AI.OpenAI.netstandard2.0.cs @@ -1,21 +1,5 @@ namespace Azure.AI.OpenAI { - public static partial class AzureChatCompletionExtensions - { - public static Azure.AI.OpenAI.Chat.AzureChatMessageContext GetAzureMessageContext(this OpenAI.Chat.ChatCompletion chatCompletion) { throw null; } - public static Azure.AI.OpenAI.ContentFilterResultForPrompt GetContentFilterResultForPrompt(this OpenAI.Chat.ChatCompletion chatCompletion) { throw null; } - public static Azure.AI.OpenAI.ContentFilterResultForResponse GetContentFilterResultForResponse(this OpenAI.Chat.ChatCompletion chatCompletion) { throw null; } - } - public static partial class AzureChatCompletionOptionsExtensions - { - public static void AddDataSource(this OpenAI.Chat.ChatCompletionOptions options, Azure.AI.OpenAI.Chat.AzureChatDataSource dataSource) { } - public static System.Collections.Generic.IReadOnlyList GetDataSources(this OpenAI.Chat.ChatCompletionOptions options) { throw null; } - } - public static partial class AzureGeneratedImageExtensions - { - public static Azure.AI.OpenAI.ImageContentFilterResultForPrompt GetContentFilterResultForPrompt(this OpenAI.Images.GeneratedImage image) { throw null; } - public static Azure.AI.OpenAI.ImageContentFilterResultForResponse GetContentFilterResultForResponse(this OpenAI.Images.GeneratedImage image) { throw null; } - } [System.Runtime.InteropServices.StructLayoutAttribute(System.Runtime.InteropServices.LayoutKind.Sequential)] public readonly partial struct AzureOpenAIAudience : System.IEquatable { @@ -62,7 +46,7 @@ public AzureOpenAIClient(System.Uri endpoint, System.ClientModel.ApiKeyCredentia } public partial class AzureOpenAIClientOptions : System.ClientModel.Primitives.ClientPipelineOptions { - public AzureOpenAIClientOptions(Azure.AI.OpenAI.AzureOpenAIClientOptions.ServiceVersion version = Azure.AI.OpenAI.AzureOpenAIClientOptions.ServiceVersion.V2024_07_01_Preview) { } + public AzureOpenAIClientOptions(Azure.AI.OpenAI.AzureOpenAIClientOptions.ServiceVersion version = Azure.AI.OpenAI.AzureOpenAIClientOptions.ServiceVersion.V2024_08_01_Preview) { } public string ApplicationId { get { throw null; } set { } } public Azure.AI.OpenAI.AzureOpenAIAudience? Audience { get { throw null; } set { } } public enum ServiceVersion @@ -71,14 +55,9 @@ public enum ServiceVersion V2024_05_01_Preview = 8, V2024_06_01 = 9, V2024_07_01_Preview = 10, + V2024_08_01_Preview = 11, } } - public static partial class AzureStreamingChatCompletionUpdateExtensions - { - public static Azure.AI.OpenAI.Chat.AzureChatMessageContext GetAzureMessageContext(this OpenAI.Chat.StreamingChatCompletionUpdate chatUpdate) { throw null; } - public static Azure.AI.OpenAI.ContentFilterResultForPrompt GetContentFilterResultForPrompt(this OpenAI.Chat.StreamingChatCompletionUpdate chatUpdate) { throw null; } - public static Azure.AI.OpenAI.ContentFilterResultForResponse GetContentFilterResultForResponse(this OpenAI.Chat.StreamingChatCompletionUpdate chatUpdate) { throw null; } - } public partial class ContentFilterBlocklistResult : System.ClientModel.Primitives.IJsonModel, System.ClientModel.Primitives.IPersistableModel { internal ContentFilterBlocklistResult() { } @@ -124,40 +103,6 @@ internal ContentFilterProtectedMaterialResult() { } string System.ClientModel.Primitives.IPersistableModel.GetFormatFromOptions(System.ClientModel.Primitives.ModelReaderWriterOptions options) { throw null; } System.BinaryData System.ClientModel.Primitives.IPersistableModel.Write(System.ClientModel.Primitives.ModelReaderWriterOptions options) { throw null; } } - public partial class ContentFilterResultForPrompt : System.ClientModel.Primitives.IJsonModel, System.ClientModel.Primitives.IPersistableModel - { - internal ContentFilterResultForPrompt() { } - public Azure.AI.OpenAI.ContentFilterBlocklistResult CustomBlocklists { get { throw null; } } - public Azure.AI.OpenAI.ContentFilterSeverityResult Hate { get { throw null; } } - public Azure.AI.OpenAI.ContentFilterDetectionResult IndirectAttack { get { throw null; } } - public Azure.AI.OpenAI.ContentFilterDetectionResult Jailbreak { get { throw null; } } - public Azure.AI.OpenAI.ContentFilterDetectionResult Profanity { get { throw null; } } - public Azure.AI.OpenAI.ContentFilterSeverityResult SelfHarm { get { throw null; } } - public Azure.AI.OpenAI.ContentFilterSeverityResult Sexual { get { throw null; } } - public Azure.AI.OpenAI.ContentFilterSeverityResult Violence { get { throw null; } } - Azure.AI.OpenAI.ContentFilterResultForPrompt System.ClientModel.Primitives.IJsonModel.Create(ref System.Text.Json.Utf8JsonReader reader, System.ClientModel.Primitives.ModelReaderWriterOptions options) { throw null; } - void System.ClientModel.Primitives.IJsonModel.Write(System.Text.Json.Utf8JsonWriter writer, System.ClientModel.Primitives.ModelReaderWriterOptions options) { } - Azure.AI.OpenAI.ContentFilterResultForPrompt System.ClientModel.Primitives.IPersistableModel.Create(System.BinaryData data, System.ClientModel.Primitives.ModelReaderWriterOptions options) { throw null; } - string System.ClientModel.Primitives.IPersistableModel.GetFormatFromOptions(System.ClientModel.Primitives.ModelReaderWriterOptions options) { throw null; } - System.BinaryData System.ClientModel.Primitives.IPersistableModel.Write(System.ClientModel.Primitives.ModelReaderWriterOptions options) { throw null; } - } - public partial class ContentFilterResultForResponse : System.ClientModel.Primitives.IJsonModel, System.ClientModel.Primitives.IPersistableModel - { - internal ContentFilterResultForResponse() { } - public Azure.AI.OpenAI.ContentFilterBlocklistResult CustomBlocklists { get { throw null; } } - public Azure.AI.OpenAI.ContentFilterSeverityResult Hate { get { throw null; } } - public Azure.AI.OpenAI.ContentFilterDetectionResult Profanity { get { throw null; } } - public Azure.AI.OpenAI.ContentFilterProtectedMaterialResult ProtectedMaterialCode { get { throw null; } } - public Azure.AI.OpenAI.ContentFilterDetectionResult ProtectedMaterialText { get { throw null; } } - public Azure.AI.OpenAI.ContentFilterSeverityResult SelfHarm { get { throw null; } } - public Azure.AI.OpenAI.ContentFilterSeverityResult Sexual { get { throw null; } } - public Azure.AI.OpenAI.ContentFilterSeverityResult Violence { get { throw null; } } - Azure.AI.OpenAI.ContentFilterResultForResponse System.ClientModel.Primitives.IJsonModel.Create(ref System.Text.Json.Utf8JsonReader reader, System.ClientModel.Primitives.ModelReaderWriterOptions options) { throw null; } - void System.ClientModel.Primitives.IJsonModel.Write(System.Text.Json.Utf8JsonWriter writer, System.ClientModel.Primitives.ModelReaderWriterOptions options) { } - Azure.AI.OpenAI.ContentFilterResultForResponse System.ClientModel.Primitives.IPersistableModel.Create(System.BinaryData data, System.ClientModel.Primitives.ModelReaderWriterOptions options) { throw null; } - string System.ClientModel.Primitives.IPersistableModel.GetFormatFromOptions(System.ClientModel.Primitives.ModelReaderWriterOptions options) { throw null; } - System.BinaryData System.ClientModel.Primitives.IPersistableModel.Write(System.ClientModel.Primitives.ModelReaderWriterOptions options) { throw null; } - } [System.Runtime.InteropServices.StructLayoutAttribute(System.Runtime.InteropServices.LayoutKind.Sequential)] public readonly partial struct ContentFilterSeverity : System.IEquatable { @@ -189,30 +134,64 @@ internal ContentFilterSeverityResult() { } string System.ClientModel.Primitives.IPersistableModel.GetFormatFromOptions(System.ClientModel.Primitives.ModelReaderWriterOptions options) { throw null; } System.BinaryData System.ClientModel.Primitives.IPersistableModel.Write(System.ClientModel.Primitives.ModelReaderWriterOptions options) { throw null; } } - public partial class ImageContentFilterResultForPrompt : Azure.AI.OpenAI.ImageContentFilterResultForResponse, System.ClientModel.Primitives.IJsonModel, System.ClientModel.Primitives.IPersistableModel + public partial class RequestContentFilterResult : System.ClientModel.Primitives.IJsonModel, System.ClientModel.Primitives.IPersistableModel + { + internal RequestContentFilterResult() { } + public Azure.AI.OpenAI.ContentFilterBlocklistResult CustomBlocklists { get { throw null; } } + public Azure.AI.OpenAI.ContentFilterSeverityResult Hate { get { throw null; } } + public Azure.AI.OpenAI.ContentFilterDetectionResult IndirectAttack { get { throw null; } } + public Azure.AI.OpenAI.ContentFilterDetectionResult Jailbreak { get { throw null; } } + public Azure.AI.OpenAI.ContentFilterDetectionResult Profanity { get { throw null; } } + public Azure.AI.OpenAI.ContentFilterSeverityResult SelfHarm { get { throw null; } } + public Azure.AI.OpenAI.ContentFilterSeverityResult Sexual { get { throw null; } } + public Azure.AI.OpenAI.ContentFilterSeverityResult Violence { get { throw null; } } + Azure.AI.OpenAI.RequestContentFilterResult System.ClientModel.Primitives.IJsonModel.Create(ref System.Text.Json.Utf8JsonReader reader, System.ClientModel.Primitives.ModelReaderWriterOptions options) { throw null; } + void System.ClientModel.Primitives.IJsonModel.Write(System.Text.Json.Utf8JsonWriter writer, System.ClientModel.Primitives.ModelReaderWriterOptions options) { } + Azure.AI.OpenAI.RequestContentFilterResult System.ClientModel.Primitives.IPersistableModel.Create(System.BinaryData data, System.ClientModel.Primitives.ModelReaderWriterOptions options) { throw null; } + string System.ClientModel.Primitives.IPersistableModel.GetFormatFromOptions(System.ClientModel.Primitives.ModelReaderWriterOptions options) { throw null; } + System.BinaryData System.ClientModel.Primitives.IPersistableModel.Write(System.ClientModel.Primitives.ModelReaderWriterOptions options) { throw null; } + } + public partial class RequestImageContentFilterResult : Azure.AI.OpenAI.ResponseImageContentFilterResult, System.ClientModel.Primitives.IJsonModel, System.ClientModel.Primitives.IPersistableModel { - internal ImageContentFilterResultForPrompt() { } + internal RequestImageContentFilterResult() { } public Azure.AI.OpenAI.ContentFilterBlocklistResult CustomBlocklists { get { throw null; } } public Azure.AI.OpenAI.ContentFilterDetectionResult Jailbreak { get { throw null; } } public Azure.AI.OpenAI.ContentFilterDetectionResult Profanity { get { throw null; } } - Azure.AI.OpenAI.ImageContentFilterResultForPrompt System.ClientModel.Primitives.IJsonModel.Create(ref System.Text.Json.Utf8JsonReader reader, System.ClientModel.Primitives.ModelReaderWriterOptions options) { throw null; } - void System.ClientModel.Primitives.IJsonModel.Write(System.Text.Json.Utf8JsonWriter writer, System.ClientModel.Primitives.ModelReaderWriterOptions options) { } - Azure.AI.OpenAI.ImageContentFilterResultForPrompt System.ClientModel.Primitives.IPersistableModel.Create(System.BinaryData data, System.ClientModel.Primitives.ModelReaderWriterOptions options) { throw null; } - string System.ClientModel.Primitives.IPersistableModel.GetFormatFromOptions(System.ClientModel.Primitives.ModelReaderWriterOptions options) { throw null; } - System.BinaryData System.ClientModel.Primitives.IPersistableModel.Write(System.ClientModel.Primitives.ModelReaderWriterOptions options) { throw null; } + Azure.AI.OpenAI.RequestImageContentFilterResult System.ClientModel.Primitives.IJsonModel.Create(ref System.Text.Json.Utf8JsonReader reader, System.ClientModel.Primitives.ModelReaderWriterOptions options) { throw null; } + void System.ClientModel.Primitives.IJsonModel.Write(System.Text.Json.Utf8JsonWriter writer, System.ClientModel.Primitives.ModelReaderWriterOptions options) { } + Azure.AI.OpenAI.RequestImageContentFilterResult System.ClientModel.Primitives.IPersistableModel.Create(System.BinaryData data, System.ClientModel.Primitives.ModelReaderWriterOptions options) { throw null; } + string System.ClientModel.Primitives.IPersistableModel.GetFormatFromOptions(System.ClientModel.Primitives.ModelReaderWriterOptions options) { throw null; } + System.BinaryData System.ClientModel.Primitives.IPersistableModel.Write(System.ClientModel.Primitives.ModelReaderWriterOptions options) { throw null; } } - public partial class ImageContentFilterResultForResponse : System.ClientModel.Primitives.IJsonModel, System.ClientModel.Primitives.IPersistableModel + public partial class ResponseContentFilterResult : System.ClientModel.Primitives.IJsonModel, System.ClientModel.Primitives.IPersistableModel { - internal ImageContentFilterResultForResponse() { } + internal ResponseContentFilterResult() { } + public Azure.AI.OpenAI.ContentFilterBlocklistResult CustomBlocklists { get { throw null; } } + public Azure.AI.OpenAI.ContentFilterSeverityResult Hate { get { throw null; } } + public Azure.AI.OpenAI.ContentFilterDetectionResult Profanity { get { throw null; } } + public Azure.AI.OpenAI.ContentFilterProtectedMaterialResult ProtectedMaterialCode { get { throw null; } } + public Azure.AI.OpenAI.ContentFilterDetectionResult ProtectedMaterialText { get { throw null; } } + public Azure.AI.OpenAI.ContentFilterSeverityResult SelfHarm { get { throw null; } } + public Azure.AI.OpenAI.ContentFilterSeverityResult Sexual { get { throw null; } } + public Azure.AI.OpenAI.ContentFilterSeverityResult Violence { get { throw null; } } + Azure.AI.OpenAI.ResponseContentFilterResult System.ClientModel.Primitives.IJsonModel.Create(ref System.Text.Json.Utf8JsonReader reader, System.ClientModel.Primitives.ModelReaderWriterOptions options) { throw null; } + void System.ClientModel.Primitives.IJsonModel.Write(System.Text.Json.Utf8JsonWriter writer, System.ClientModel.Primitives.ModelReaderWriterOptions options) { } + Azure.AI.OpenAI.ResponseContentFilterResult System.ClientModel.Primitives.IPersistableModel.Create(System.BinaryData data, System.ClientModel.Primitives.ModelReaderWriterOptions options) { throw null; } + string System.ClientModel.Primitives.IPersistableModel.GetFormatFromOptions(System.ClientModel.Primitives.ModelReaderWriterOptions options) { throw null; } + System.BinaryData System.ClientModel.Primitives.IPersistableModel.Write(System.ClientModel.Primitives.ModelReaderWriterOptions options) { throw null; } + } + public partial class ResponseImageContentFilterResult : System.ClientModel.Primitives.IJsonModel, System.ClientModel.Primitives.IPersistableModel + { + internal ResponseImageContentFilterResult() { } public Azure.AI.OpenAI.ContentFilterSeverityResult Hate { get { throw null; } } public Azure.AI.OpenAI.ContentFilterSeverityResult SelfHarm { get { throw null; } } public Azure.AI.OpenAI.ContentFilterSeverityResult Sexual { get { throw null; } } public Azure.AI.OpenAI.ContentFilterSeverityResult Violence { get { throw null; } } - Azure.AI.OpenAI.ImageContentFilterResultForResponse System.ClientModel.Primitives.IJsonModel.Create(ref System.Text.Json.Utf8JsonReader reader, System.ClientModel.Primitives.ModelReaderWriterOptions options) { throw null; } - void System.ClientModel.Primitives.IJsonModel.Write(System.Text.Json.Utf8JsonWriter writer, System.ClientModel.Primitives.ModelReaderWriterOptions options) { } - Azure.AI.OpenAI.ImageContentFilterResultForResponse System.ClientModel.Primitives.IPersistableModel.Create(System.BinaryData data, System.ClientModel.Primitives.ModelReaderWriterOptions options) { throw null; } - string System.ClientModel.Primitives.IPersistableModel.GetFormatFromOptions(System.ClientModel.Primitives.ModelReaderWriterOptions options) { throw null; } - System.BinaryData System.ClientModel.Primitives.IPersistableModel.Write(System.ClientModel.Primitives.ModelReaderWriterOptions options) { throw null; } + Azure.AI.OpenAI.ResponseImageContentFilterResult System.ClientModel.Primitives.IJsonModel.Create(ref System.Text.Json.Utf8JsonReader reader, System.ClientModel.Primitives.ModelReaderWriterOptions options) { throw null; } + void System.ClientModel.Primitives.IJsonModel.Write(System.Text.Json.Utf8JsonWriter writer, System.ClientModel.Primitives.ModelReaderWriterOptions options) { } + Azure.AI.OpenAI.ResponseImageContentFilterResult System.ClientModel.Primitives.IPersistableModel.Create(System.BinaryData data, System.ClientModel.Primitives.ModelReaderWriterOptions options) { throw null; } + string System.ClientModel.Primitives.IPersistableModel.GetFormatFromOptions(System.ClientModel.Primitives.ModelReaderWriterOptions options) { throw null; } + System.BinaryData System.ClientModel.Primitives.IPersistableModel.Write(System.ClientModel.Primitives.ModelReaderWriterOptions options) { throw null; } } } namespace Azure.AI.OpenAI.Chat @@ -223,6 +202,7 @@ internal AzureChatCitation() { } public string ChunkId { get { throw null; } } public string Content { get { throw null; } } public string Filepath { get { throw null; } } + public double? RerankScore { get { throw null; } } public string Title { get { throw null; } } public string Url { get { throw null; } } Azure.AI.OpenAI.Chat.AzureChatCitation System.ClientModel.Primitives.IJsonModel.Create(ref System.Text.Json.Utf8JsonReader reader, System.ClientModel.Primitives.ModelReaderWriterOptions options) { throw null; } @@ -231,6 +211,17 @@ internal AzureChatCitation() { } string System.ClientModel.Primitives.IPersistableModel.GetFormatFromOptions(System.ClientModel.Primitives.ModelReaderWriterOptions options) { throw null; } System.BinaryData System.ClientModel.Primitives.IPersistableModel.Write(System.ClientModel.Primitives.ModelReaderWriterOptions options) { throw null; } } + public static partial class AzureChatCompletionExtensions + { + public static Azure.AI.OpenAI.Chat.AzureChatMessageContext GetAzureMessageContext(this OpenAI.Chat.ChatCompletion chatCompletion) { throw null; } + public static Azure.AI.OpenAI.RequestContentFilterResult GetRequestContentFilterResult(this OpenAI.Chat.ChatCompletion chatCompletion) { throw null; } + public static Azure.AI.OpenAI.ResponseContentFilterResult GetResponseContentFilterResult(this OpenAI.Chat.ChatCompletion chatCompletion) { throw null; } + } + public static partial class AzureChatCompletionOptionsExtensions + { + public static void AddDataSource(this OpenAI.Chat.ChatCompletionOptions options, Azure.AI.OpenAI.Chat.AzureChatDataSource dataSource) { } + public static System.Collections.Generic.IReadOnlyList GetDataSources(this OpenAI.Chat.ChatCompletionOptions options) { throw null; } + } public abstract partial class AzureChatDataSource : System.ClientModel.Primitives.IJsonModel, System.ClientModel.Primitives.IPersistableModel { protected AzureChatDataSource() { } @@ -301,8 +292,7 @@ public AzureCosmosDBChatDataSource() { } public string IndexName { get { throw null; } set { } } public bool? InScope { get { throw null; } set { } } public int? MaxSearchQueries { get { throw null; } set { } } - public Azure.AI.OpenAI.Chat.DataSourceOutputContextFlags? OutputContextFlags { get { throw null; } set { } } - public string RoleInformation { get { throw null; } set { } } + public Azure.AI.OpenAI.Chat.DataSourceOutputContexts? OutputContextFlags { get { throw null; } set { } } public int? Strictness { get { throw null; } set { } } public int? TopNDocuments { get { throw null; } set { } } public Azure.AI.OpenAI.Chat.DataSourceVectorizer VectorizationSource { get { throw null; } set { } } @@ -312,28 +302,6 @@ public AzureCosmosDBChatDataSource() { } string System.ClientModel.Primitives.IPersistableModel.GetFormatFromOptions(System.ClientModel.Primitives.ModelReaderWriterOptions options) { throw null; } System.BinaryData System.ClientModel.Primitives.IPersistableModel.Write(System.ClientModel.Primitives.ModelReaderWriterOptions options) { throw null; } } - public partial class AzureMachineLearningIndexChatDataSource : Azure.AI.OpenAI.Chat.AzureChatDataSource, System.ClientModel.Primitives.IJsonModel, System.ClientModel.Primitives.IPersistableModel - { - [System.ObsoleteAttribute("Constructors of types with required members are not supported in this version of your compiler.", true)] - public AzureMachineLearningIndexChatDataSource() { } - public bool? AllowPartialResult { get { throw null; } set { } } - public Azure.AI.OpenAI.Chat.DataSourceAuthentication Authentication { get { throw null; } set { } } - public string Filter { get { throw null; } set { } } - public string IndexName { get { throw null; } set { } } - public bool? InScope { get { throw null; } set { } } - public int? MaxSearchQueries { get { throw null; } set { } } - public Azure.AI.OpenAI.Chat.DataSourceOutputContextFlags? OutputContextFlags { get { throw null; } set { } } - public string ProjectResourceId { get { throw null; } set { } } - public string RoleInformation { get { throw null; } set { } } - public int? Strictness { get { throw null; } set { } } - public int? TopNDocuments { get { throw null; } set { } } - public string Version { get { throw null; } set { } } - Azure.AI.OpenAI.Chat.AzureMachineLearningIndexChatDataSource System.ClientModel.Primitives.IJsonModel.Create(ref System.Text.Json.Utf8JsonReader reader, System.ClientModel.Primitives.ModelReaderWriterOptions options) { throw null; } - void System.ClientModel.Primitives.IJsonModel.Write(System.Text.Json.Utf8JsonWriter writer, System.ClientModel.Primitives.ModelReaderWriterOptions options) { } - Azure.AI.OpenAI.Chat.AzureMachineLearningIndexChatDataSource System.ClientModel.Primitives.IPersistableModel.Create(System.BinaryData data, System.ClientModel.Primitives.ModelReaderWriterOptions options) { throw null; } - string System.ClientModel.Primitives.IPersistableModel.GetFormatFromOptions(System.ClientModel.Primitives.ModelReaderWriterOptions options) { throw null; } - System.BinaryData System.ClientModel.Primitives.IPersistableModel.Write(System.ClientModel.Primitives.ModelReaderWriterOptions options) { throw null; } - } public partial class AzureSearchChatDataSource : Azure.AI.OpenAI.Chat.AzureChatDataSource, System.ClientModel.Primitives.IJsonModel, System.ClientModel.Primitives.IPersistableModel { [System.ObsoleteAttribute("Constructors of types with required members are not supported in this version of your compiler.", true)] @@ -346,9 +314,8 @@ public AzureSearchChatDataSource() { } public string IndexName { get { throw null; } set { } } public bool? InScope { get { throw null; } set { } } public int? MaxSearchQueries { get { throw null; } set { } } - public Azure.AI.OpenAI.Chat.DataSourceOutputContextFlags? OutputContextFlags { get { throw null; } set { } } + public Azure.AI.OpenAI.Chat.DataSourceOutputContexts? OutputContextFlags { get { throw null; } set { } } public Azure.AI.OpenAI.Chat.DataSourceQueryType? QueryType { get { throw null; } set { } } - public string RoleInformation { get { throw null; } set { } } public string SemanticConfiguration { get { throw null; } set { } } public int? Strictness { get { throw null; } set { } } public int? TopNDocuments { get { throw null; } set { } } @@ -359,6 +326,12 @@ public AzureSearchChatDataSource() { } string System.ClientModel.Primitives.IPersistableModel.GetFormatFromOptions(System.ClientModel.Primitives.ModelReaderWriterOptions options) { throw null; } System.BinaryData System.ClientModel.Primitives.IPersistableModel.Write(System.ClientModel.Primitives.ModelReaderWriterOptions options) { throw null; } } + public static partial class AzureStreamingChatCompletionUpdateExtensions + { + public static Azure.AI.OpenAI.Chat.AzureChatMessageContext GetAzureMessageContext(this OpenAI.Chat.StreamingChatCompletionUpdate chatUpdate) { throw null; } + public static Azure.AI.OpenAI.RequestContentFilterResult GetRequestContentFilterResult(this OpenAI.Chat.StreamingChatCompletionUpdate chatUpdate) { throw null; } + public static Azure.AI.OpenAI.ResponseContentFilterResult GetResponseContentFilterResult(this OpenAI.Chat.StreamingChatCompletionUpdate chatUpdate) { throw null; } + } public abstract partial class DataSourceAuthentication : System.ClientModel.Primitives.IJsonModel, System.ClientModel.Primitives.IPersistableModel { protected DataSourceAuthentication() { } @@ -369,6 +342,7 @@ protected DataSourceAuthentication() { } public static Azure.AI.OpenAI.Chat.DataSourceAuthentication FromKeyAndKeyId(string key, string keyId) { throw null; } public static Azure.AI.OpenAI.Chat.DataSourceAuthentication FromSystemManagedIdentity() { throw null; } public static Azure.AI.OpenAI.Chat.DataSourceAuthentication FromUserManagedIdentity(string identityResourceId) { throw null; } + public static Azure.AI.OpenAI.Chat.DataSourceAuthentication FromUsernameAndPassword(string username, string password) { throw null; } Azure.AI.OpenAI.Chat.DataSourceAuthentication System.ClientModel.Primitives.IJsonModel.Create(ref System.Text.Json.Utf8JsonReader reader, System.ClientModel.Primitives.ModelReaderWriterOptions options) { throw null; } void System.ClientModel.Primitives.IJsonModel.Write(System.Text.Json.Utf8JsonWriter writer, System.ClientModel.Primitives.ModelReaderWriterOptions options) { } Azure.AI.OpenAI.Chat.DataSourceAuthentication System.ClientModel.Primitives.IPersistableModel.Create(System.BinaryData data, System.ClientModel.Primitives.ModelReaderWriterOptions options) { throw null; } @@ -392,7 +366,7 @@ public DataSourceFieldMappings() { } System.BinaryData System.ClientModel.Primitives.IPersistableModel.Write(System.ClientModel.Primitives.ModelReaderWriterOptions options) { throw null; } } [System.FlagsAttribute] - public enum DataSourceOutputContextFlags + public enum DataSourceOutputContexts { Intent = 1, Citations = 2, @@ -424,6 +398,7 @@ public abstract partial class DataSourceVectorizer : System.ClientModel.Primitiv protected DataSourceVectorizer() { } public static Azure.AI.OpenAI.Chat.DataSourceVectorizer FromDeploymentName(string deploymentName) { throw null; } public static Azure.AI.OpenAI.Chat.DataSourceVectorizer FromEndpoint(System.Uri endpoint, Azure.AI.OpenAI.Chat.DataSourceAuthentication authentication) { throw null; } + public static Azure.AI.OpenAI.Chat.DataSourceVectorizer FromIntegratedResource() { throw null; } public static Azure.AI.OpenAI.Chat.DataSourceVectorizer FromModelId(string modelId) { throw null; } Azure.AI.OpenAI.Chat.DataSourceVectorizer System.ClientModel.Primitives.IJsonModel.Create(ref System.Text.Json.Utf8JsonReader reader, System.ClientModel.Primitives.ModelReaderWriterOptions options) { throw null; } void System.ClientModel.Primitives.IJsonModel.Write(System.Text.Json.Utf8JsonWriter writer, System.ClientModel.Primitives.ModelReaderWriterOptions options) { } @@ -442,9 +417,8 @@ public ElasticsearchChatDataSource() { } public string IndexName { get { throw null; } set { } } public bool? InScope { get { throw null; } set { } } public int? MaxSearchQueries { get { throw null; } set { } } - public Azure.AI.OpenAI.Chat.DataSourceOutputContextFlags? OutputContextFlags { get { throw null; } set { } } + public Azure.AI.OpenAI.Chat.DataSourceOutputContexts? OutputContextFlags { get { throw null; } set { } } public Azure.AI.OpenAI.Chat.DataSourceQueryType? QueryType { get { throw null; } set { } } - public string RoleInformation { get { throw null; } set { } } public int? Strictness { get { throw null; } set { } } public int? TopNDocuments { get { throw null; } set { } } public Azure.AI.OpenAI.Chat.DataSourceVectorizer VectorizationSource { get { throw null; } set { } } @@ -454,6 +428,28 @@ public ElasticsearchChatDataSource() { } string System.ClientModel.Primitives.IPersistableModel.GetFormatFromOptions(System.ClientModel.Primitives.ModelReaderWriterOptions options) { throw null; } System.BinaryData System.ClientModel.Primitives.IPersistableModel.Write(System.ClientModel.Primitives.ModelReaderWriterOptions options) { throw null; } } + public partial class MongoDBChatDataSource : Azure.AI.OpenAI.Chat.AzureChatDataSource, System.ClientModel.Primitives.IJsonModel, System.ClientModel.Primitives.IPersistableModel + { + [System.ObsoleteAttribute("Constructors of types with required members are not supported in this version of your compiler.", true)] + public MongoDBChatDataSource() { } + public bool? AllowPartialResult { get { throw null; } set { } } + public string AppName { get { throw null; } set { } } + public Azure.AI.OpenAI.Chat.DataSourceAuthentication Authentication { get { throw null; } set { } } + public string CollectionName { get { throw null; } set { } } + public string EndpointName { get { throw null; } set { } } + public string IndexName { get { throw null; } set { } } + public bool? InScope { get { throw null; } set { } } + public int? MaxSearchQueries { get { throw null; } set { } } + public Azure.AI.OpenAI.Chat.DataSourceOutputContexts? OutputContextFlags { get { throw null; } set { } } + public int? Strictness { get { throw null; } set { } } + public int? TopNDocuments { get { throw null; } set { } } + public Azure.AI.OpenAI.Chat.DataSourceVectorizer VectorizationSource { get { throw null; } set { } } + Azure.AI.OpenAI.Chat.MongoDBChatDataSource System.ClientModel.Primitives.IJsonModel.Create(ref System.Text.Json.Utf8JsonReader reader, System.ClientModel.Primitives.ModelReaderWriterOptions options) { throw null; } + void System.ClientModel.Primitives.IJsonModel.Write(System.Text.Json.Utf8JsonWriter writer, System.ClientModel.Primitives.ModelReaderWriterOptions options) { } + Azure.AI.OpenAI.Chat.MongoDBChatDataSource System.ClientModel.Primitives.IPersistableModel.Create(System.BinaryData data, System.ClientModel.Primitives.ModelReaderWriterOptions options) { throw null; } + string System.ClientModel.Primitives.IPersistableModel.GetFormatFromOptions(System.ClientModel.Primitives.ModelReaderWriterOptions options) { throw null; } + System.BinaryData System.ClientModel.Primitives.IPersistableModel.Write(System.ClientModel.Primitives.ModelReaderWriterOptions options) { throw null; } + } public partial class PineconeChatDataSource : Azure.AI.OpenAI.Chat.AzureChatDataSource, System.ClientModel.Primitives.IJsonModel, System.ClientModel.Primitives.IPersistableModel { [System.ObsoleteAttribute("Constructors of types with required members are not supported in this version of your compiler.", true)] @@ -465,8 +461,7 @@ public PineconeChatDataSource() { } public string IndexName { get { throw null; } set { } } public bool? InScope { get { throw null; } set { } } public int? MaxSearchQueries { get { throw null; } set { } } - public Azure.AI.OpenAI.Chat.DataSourceOutputContextFlags? OutputContextFlags { get { throw null; } set { } } - public string RoleInformation { get { throw null; } set { } } + public Azure.AI.OpenAI.Chat.DataSourceOutputContexts? OutputContextFlags { get { throw null; } set { } } public int? Strictness { get { throw null; } set { } } public int? TopNDocuments { get { throw null; } set { } } public Azure.AI.OpenAI.Chat.DataSourceVectorizer VectorizationSource { get { throw null; } set { } } @@ -477,3 +472,11 @@ public PineconeChatDataSource() { } System.BinaryData System.ClientModel.Primitives.IPersistableModel.Write(System.ClientModel.Primitives.ModelReaderWriterOptions options) { throw null; } } } +namespace Azure.AI.OpenAI.Images +{ + public static partial class AzureGeneratedImageExtensions + { + public static Azure.AI.OpenAI.RequestImageContentFilterResult GetRequestContentFilterResult(this OpenAI.Images.GeneratedImage image) { throw null; } + public static Azure.AI.OpenAI.ResponseImageContentFilterResult GetResponseContentFilterResult(this OpenAI.Images.GeneratedImage image) { throw null; } + } +} diff --git a/sdk/openai/Azure.AI.OpenAI/assets.json b/sdk/openai/Azure.AI.OpenAI/assets.json index 39d86235b486..d4627c89fd84 100644 --- a/sdk/openai/Azure.AI.OpenAI/assets.json +++ b/sdk/openai/Azure.AI.OpenAI/assets.json @@ -2,5 +2,5 @@ "AssetsRepo": "Azure/azure-sdk-assets", "AssetsRepoPrefixPath": "net", "TagPrefix": "net/openai/Azure.AI.OpenAI", - "Tag": "net/openai/Azure.AI.OpenAI_23ae923738" + "Tag": "net/openai/Azure.AI.OpenAI_39ae840db6" } diff --git a/sdk/openai/Azure.AI.OpenAI/src/Azure.AI.OpenAI.csproj b/sdk/openai/Azure.AI.OpenAI/src/Azure.AI.OpenAI.csproj index b8070ffcf523..fb573d3a2181 100644 --- a/sdk/openai/Azure.AI.OpenAI/src/Azure.AI.OpenAI.csproj +++ b/sdk/openai/Azure.AI.OpenAI/src/Azure.AI.OpenAI.csproj @@ -37,10 +37,7 @@ - - - - + @@ -56,13 +53,11 @@ - - - + diff --git a/sdk/openai/Azure.AI.OpenAI/src/Custom/Assistants/AzureAssistantClient.Protocol.cs b/sdk/openai/Azure.AI.OpenAI/src/Custom/Assistants/AzureAssistantClient.Protocol.cs index c1c987098677..236a54231198 100644 --- a/sdk/openai/Azure.AI.OpenAI/src/Custom/Assistants/AzureAssistantClient.Protocol.cs +++ b/sdk/openai/Azure.AI.OpenAI/src/Custom/Assistants/AzureAssistantClient.Protocol.cs @@ -4,6 +4,7 @@ using System.ClientModel; using System.ClientModel.Primitives; using System.Diagnostics.CodeAnalysis; +using Azure.AI.OpenAI.Utility; namespace Azure.AI.OpenAI.Assistants; @@ -26,16 +27,25 @@ public override ClientResult CreateAssistant(BinaryContent content, RequestOptio return ClientResult.FromResponse(Pipeline.ProcessMessage(message, options)); } - public override IAsyncEnumerable GetAssistantsAsync(int? limit, string order, string after, string before, RequestOptions options) + public override AsyncCollectionResult GetAssistantsAsync(int? limit, string order, string after, string before, RequestOptions options) { - AzureAssistantsPageEnumerator enumerator = new(Pipeline, _endpoint, limit, order, after, before, _apiVersion, options); - return PageCollectionHelpers.CreateAsync(enumerator); + return new AzureAsyncCollectionResult( + Pipeline, + options, + continuation => CreateGetAssistantsRequest(limit, order, continuation?.After ?? after, continuation?.Before ?? before, options), + page => AssistantCollectionPageToken.FromResponse(page, limit, order, before), + page => ModelReaderWriter.Read(page.GetRawResponse().Content).Data, + options?.CancellationToken ?? default); } - public override IEnumerable GetAssistants(int? limit, string order, string after, string before, RequestOptions options) + public override CollectionResult GetAssistants(int? limit, string order, string after, string before, RequestOptions options) { - AzureAssistantsPageEnumerator enumerator = new(Pipeline, _endpoint, limit, order, after, before, _apiVersion, options); - return PageCollectionHelpers.Create(enumerator); + return new AzureCollectionResult( + Pipeline, + options, + continuation => CreateGetAssistantsRequest(limit, order, continuation?.After ?? after, continuation?.Before ?? before, options), + page => AssistantCollectionPageToken.FromResponse(page, limit, order, before), + page => ModelReaderWriter.Read(page.GetRawResponse().Content).Data); } public override async Task GetAssistantAsync(string assistantId, RequestOptions options) @@ -107,20 +117,27 @@ public override ClientResult CreateMessage(string threadId, BinaryContent conten } /// - public override IAsyncEnumerable GetMessagesAsync(string threadId, int? limit, string order, string after, string before, RequestOptions options) + public override AsyncCollectionResult GetMessagesAsync(string threadId, int? limit, string order, string after, string before, RequestOptions options) { Argument.AssertNotNullOrEmpty(threadId, nameof(threadId)); - - AzureMessagesPageEnumerator enumerator = new(Pipeline, _endpoint, threadId, limit, order, after, before, _apiVersion, options); - return PageCollectionHelpers.CreateAsync(enumerator); + return new AzureAsyncCollectionResult( + Pipeline, + options, + continuation => CreateGetMessagesRequest(threadId, limit, order, continuation?.After ?? after, continuation?.Before ?? before, options), + page => MessageCollectionPageToken.FromResponse(page, threadId, limit, order, before), + page => ModelReaderWriter.Read(page.GetRawResponse().Content).Data, + options?.CancellationToken ?? default); } - public override IEnumerable GetMessages(string threadId, int? limit, string order, string after, string before, RequestOptions options) + public override CollectionResult GetMessages(string threadId, int? limit, string order, string after, string before, RequestOptions options) { Argument.AssertNotNullOrEmpty(threadId, nameof(threadId)); - - AzureMessagesPageEnumerator enumerator = new(Pipeline, _endpoint, threadId, limit, order, after, before, _apiVersion, options); - return PageCollectionHelpers.Create(enumerator); + return new AzureCollectionResult( + Pipeline, + options, + continuation => CreateGetMessagesRequest(threadId, limit, order, continuation?.After ?? after, continuation?.Before ?? before, options), + page => MessageCollectionPageToken.FromResponse(page, threadId, limit, order, before), + page => ModelReaderWriter.Read(page.GetRawResponse().Content).Data); } /// @@ -257,20 +274,27 @@ public override ClientResult CreateRun(string threadId, BinaryContent content, R } } - public override IAsyncEnumerable GetRunsAsync(string threadId, int? limit, string order, string after, string before, RequestOptions options) + public override AsyncCollectionResult GetRunsAsync(string threadId, int? limit, string order, string after, string before, RequestOptions options) { Argument.AssertNotNullOrEmpty(threadId, nameof(threadId)); - - AzureRunsPageEnumerator enumerator = new(Pipeline, _endpoint, threadId, limit, order, after, before, _apiVersion, options); - return PageCollectionHelpers.CreateAsync(enumerator); + return new AzureAsyncCollectionResult( + Pipeline, + options, + continuation => CreateGetRunsRequest(threadId, limit, order, continuation?.After ?? after, continuation?.Before ?? before, options), + page => RunCollectionPageToken.FromResponse(page, threadId, limit, order, before), + page => ModelReaderWriter.Read(page.GetRawResponse().Content).Data, + options?.CancellationToken ?? default); } - public override IEnumerable GetRuns(string threadId, int? limit, string order, string after, string before, RequestOptions options) + public override CollectionResult GetRuns(string threadId, int? limit, string order, string after, string before, RequestOptions options) { Argument.AssertNotNullOrEmpty(threadId, nameof(threadId)); - - AzureRunsPageEnumerator enumerator = new(Pipeline, _endpoint, threadId, limit, order, after, before, _apiVersion, options); - return PageCollectionHelpers.Create(enumerator); + return new AzureCollectionResult( + Pipeline, + options, + continuation => CreateGetRunsRequest(threadId, limit, order, continuation?.After ?? after, continuation?.Before ?? before, options), + page => RunCollectionPageToken.FromResponse(page, threadId, limit, order, before), + page => ModelReaderWriter.Read(page.GetRawResponse().Content).Data); } /// @@ -375,22 +399,31 @@ public override ClientResult SubmitToolOutputsToRun(string threadId, string runI } } - public override IAsyncEnumerable GetRunStepsAsync(string threadId, string runId, int? limit, string order, string after, string before, RequestOptions options) + public override AsyncCollectionResult GetRunStepsAsync(string threadId, string runId, int? limit, string order, string after, string before, RequestOptions options) { Argument.AssertNotNullOrEmpty(threadId, nameof(threadId)); Argument.AssertNotNullOrEmpty(runId, nameof(runId)); - AzureRunStepsPageEnumerator enumerator = new(Pipeline, _endpoint, threadId, runId, limit, order, after, before, _apiVersion, options); - return PageCollectionHelpers.CreateAsync(enumerator); + return new AzureAsyncCollectionResult( + Pipeline, + options, + continuation => CreateGetRunStepsRequest(threadId, runId, limit, order, continuation?.After ?? after, continuation?.Before ?? before, options), + page => RunStepCollectionPageToken.FromResponse(page, threadId, runId, limit, order, before), + page => ModelReaderWriter.Read(page.GetRawResponse().Content).Data, + options?.CancellationToken ?? default); } - public override IEnumerable GetRunSteps(string threadId, string runId, int? limit, string order, string after, string before, RequestOptions options) + public override CollectionResult GetRunSteps(string threadId, string runId, int? limit, string order, string after, string before, RequestOptions options) { Argument.AssertNotNullOrEmpty(threadId, nameof(threadId)); Argument.AssertNotNullOrEmpty(runId, nameof(runId)); - AzureRunStepsPageEnumerator enumerator = new(Pipeline, _endpoint, threadId, runId, limit, order, after, before, _apiVersion, options); - return PageCollectionHelpers.Create(enumerator); + return new AzureCollectionResult( + Pipeline, + options, + continuation => CreateGetRunStepsRequest(threadId, runId, limit, order, continuation?.After ?? after, continuation?.Before ?? before, options), + page => RunStepCollectionPageToken.FromResponse(page, threadId, runId, limit, order, before), + page => ModelReaderWriter.Read(page.GetRawResponse().Content).Data); } /// @@ -486,6 +519,9 @@ public override ClientResult DeleteThread(string threadId, RequestOptions option private new PipelineMessage CreateCreateAssistantRequest(BinaryContent content, RequestOptions options = null) => NewJsonPostBuilder(content, options).WithPath("assistants").Build(); + private new PipelineMessage CreateGetAssistantsRequest(int? limit, string order, string after, string before, RequestOptions options) + => NewGetListBuilder(limit, order, after, before, options).WithPath("assistants").Build(); + private new PipelineMessage CreateGetAssistantRequest(string assistantId, RequestOptions options) => NewJsonGetBuilder(options).WithPath("assistants", assistantId).Build(); @@ -513,6 +549,9 @@ private PipelineMessage CreateDeleteThreadRequest(string threadId, RequestOption private PipelineMessage CreateCreateMessageRequest(string threadId, BinaryContent content, RequestOptions options) => NewJsonPostBuilder(content, options).WithPath("threads", threadId, "messages").Build(); + private PipelineMessage CreateGetMessagesRequest(string threadId, int? limit, string order, string after, string before, RequestOptions options) + => NewGetListBuilder(limit, order, after, before, options).WithPath("threads", threadId, "messages").Build(); + private PipelineMessage CreateGetMessageRequest(string threadId, string messageId, RequestOptions options) => NewJsonGetBuilder(options).WithPath("threads", threadId, "messages", messageId).Build(); @@ -528,6 +567,9 @@ private PipelineMessage CreateCreateThreadAndRunRequest(BinaryContent content, R private PipelineMessage CreateCreateRunRequest(string threadId, BinaryContent content, RequestOptions options) => NewJsonPostBuilder(content, options).WithPath("threads", threadId, "runs").Build(); + private PipelineMessage CreateGetRunsRequest(string threadId, int? limit, string order, string after, string before, RequestOptions options) + => NewGetListBuilder(limit, order, after, before, options).WithPath("threads", threadId, "runs").Build(); + private PipelineMessage CreateGetRunRequest(string threadId, string runId, RequestOptions options) => NewJsonGetBuilder(options).WithPath("threads", threadId, "runs", runId).Build(); @@ -540,6 +582,9 @@ private PipelineMessage CreateCancelRunRequest(string threadId, string runId, Re private PipelineMessage CreateSubmitToolOutputsToRunRequest(string threadId, string runId, BinaryContent content, RequestOptions options) => NewJsonPostBuilder(content, options).WithPath("threads", threadId, "runs", runId, "submit_tool_outputs").Build(); + private PipelineMessage CreateGetRunStepsRequest(string threadId, string runId, int? limit, string order, string after, string before, RequestOptions options) + => NewGetListBuilder(limit, order, after, before, options).WithPath("threads", threadId, "runs", runId, "steps").Build(); + private PipelineMessage CreateGetRunStepRequest(string threadId, string runId, string stepId, RequestOptions options) => NewJsonGetBuilder(options).WithPath("threads", threadId, "runs", runId, "steps", stepId).Build(); diff --git a/sdk/openai/Azure.AI.OpenAI/src/Custom/Assistants/Internal/Pagination/AzureAssistantsPageEnumerator.cs b/sdk/openai/Azure.AI.OpenAI/src/Custom/Assistants/Internal/Pagination/AzureAssistantsPageEnumerator.cs deleted file mode 100644 index f351279a7f04..000000000000 --- a/sdk/openai/Azure.AI.OpenAI/src/Custom/Assistants/Internal/Pagination/AzureAssistantsPageEnumerator.cs +++ /dev/null @@ -1,49 +0,0 @@ -// Copyright (c) Microsoft Corporation. All rights reserved. -// Licensed under the MIT License. - -using System.ClientModel; -using System.ClientModel.Primitives; - -#nullable enable - -namespace Azure.AI.OpenAI.Assistants; - -internal partial class AzureAssistantsPageEnumerator : AssistantsPageEnumerator -{ - private readonly Uri _endpoint; - private readonly string _apiVersion; - - public AzureAssistantsPageEnumerator( - ClientPipeline pipeline, - Uri endpoint, - int? limit, string order, string after, string before, - string apiVersion, - RequestOptions options) - : base(pipeline, endpoint, limit, order, after, before, options) - { - _endpoint = endpoint; - _apiVersion = apiVersion; - } - - internal override async Task GetAssistantsAsync(int? limit, string order, string after, string before, RequestOptions options) - { - using PipelineMessage message = CreateGetAssistantsRequest(limit, order, after, before, options); - return ClientResult.FromResponse(await Pipeline.ProcessMessageAsync(message, options).ConfigureAwait(false)); - } - - internal override ClientResult GetAssistants(int? limit, string order, string after, string before, RequestOptions options) - { - using PipelineMessage message = CreateGetAssistantsRequest(limit, order, after, before, options); - return ClientResult.FromResponse(Pipeline.ProcessMessage(message, options)); - } - - private PipelineMessage CreateGetAssistantsRequest(int? limit, string order, string after, string before, RequestOptions options) - => new AzureOpenAIPipelineMessageBuilder(Pipeline, _endpoint, _apiVersion) - .WithAssistantsHeader() - .WithOptions(options) - .WithMethod("GET") - .WithAccept("application/json") - .WithCommonListParameters(limit, order, after, before) - .WithPath("assistants") - .Build(); -} diff --git a/sdk/openai/Azure.AI.OpenAI/src/Custom/Assistants/Internal/Pagination/AzureMessagesPageEnumerator.cs b/sdk/openai/Azure.AI.OpenAI/src/Custom/Assistants/Internal/Pagination/AzureMessagesPageEnumerator.cs deleted file mode 100644 index 79ad28d13aa4..000000000000 --- a/sdk/openai/Azure.AI.OpenAI/src/Custom/Assistants/Internal/Pagination/AzureMessagesPageEnumerator.cs +++ /dev/null @@ -1,52 +0,0 @@ -// Copyright (c) Microsoft Corporation. All rights reserved. -// Licensed under the MIT License. - -using System.ClientModel; -using System.ClientModel.Primitives; - -namespace Azure.AI.OpenAI.Assistants; - -internal partial class AzureMessagesPageEnumerator : MessagesPageEnumerator -{ - private readonly Uri _endpoint; - private readonly string _apiVersion; - - public AzureMessagesPageEnumerator( - ClientPipeline pipeline, - Uri endpoint, - string threadId, - int? limit, string order, string after, string before, - string apiVersion, - RequestOptions options) - : base(pipeline, endpoint, threadId, limit, order, after, before, options) - { - _endpoint = endpoint; - _apiVersion = apiVersion; - } - - internal override async Task GetMessagesAsync(string threadId, int? limit, string order, string after, string before, RequestOptions options) - { - Argument.AssertNotNullOrEmpty(threadId, nameof(threadId)); - - using PipelineMessage message = CreateGetMessagesRequest(threadId, limit, order, after, before, options); - return ClientResult.FromResponse(await Pipeline.ProcessMessageAsync(message, options).ConfigureAwait(false)); - } - - internal override ClientResult GetMessages(string threadId, int? limit, string order, string after, string before, RequestOptions options) - { - Argument.AssertNotNullOrEmpty(threadId, nameof(threadId)); - - using PipelineMessage message = CreateGetMessagesRequest(threadId, limit, order, after, before, options); - return ClientResult.FromResponse(Pipeline.ProcessMessage(message, options)); - } - - private PipelineMessage CreateGetMessagesRequest(string threadId, int? limit, string order, string after, string before, RequestOptions options) - => new AzureOpenAIPipelineMessageBuilder(Pipeline, _endpoint, _apiVersion) - .WithAssistantsHeader() - .WithOptions(options) - .WithMethod("GET") - .WithAccept("application/json") - .WithCommonListParameters(limit, order, after, before) - .WithPath("threads", threadId, "messages") - .Build(); -} diff --git a/sdk/openai/Azure.AI.OpenAI/src/Custom/Assistants/Internal/Pagination/AzureRunStepsPageEnumerator.cs b/sdk/openai/Azure.AI.OpenAI/src/Custom/Assistants/Internal/Pagination/AzureRunStepsPageEnumerator.cs deleted file mode 100644 index e7f6ae90293f..000000000000 --- a/sdk/openai/Azure.AI.OpenAI/src/Custom/Assistants/Internal/Pagination/AzureRunStepsPageEnumerator.cs +++ /dev/null @@ -1,54 +0,0 @@ -// Copyright (c) Microsoft Corporation. All rights reserved. -// Licensed under the MIT License. - -using System.ClientModel; -using System.ClientModel.Primitives; - -namespace Azure.AI.OpenAI.Assistants; - -internal partial class AzureRunStepsPageEnumerator : RunStepsPageEnumerator -{ - private readonly Uri _endpoint; - private readonly string _apiVersion; - - public AzureRunStepsPageEnumerator( - ClientPipeline pipeline, - Uri endpoint, - string threadId, string runId, - int? limit, string order, string after, string before, - string apiVersion, - RequestOptions options) - : base(pipeline, endpoint, threadId, runId, limit, order, after, before, options) - { - _endpoint = endpoint; - _apiVersion = apiVersion; - } - - internal override async Task GetRunStepsAsync(string threadId, string runId, int? limit, string order, string after, string before, RequestOptions options) - { - Argument.AssertNotNullOrEmpty(threadId, nameof(threadId)); - Argument.AssertNotNullOrEmpty(runId, nameof(runId)); - - using PipelineMessage message = CreateGetRunStepsRequest(threadId, runId, limit, order, after, before, options); - return ClientResult.FromResponse(await Pipeline.ProcessMessageAsync(message, options).ConfigureAwait(false)); - } - - internal override ClientResult GetRunSteps(string threadId, string runId, int? limit, string order, string after, string before, RequestOptions options) - { - Argument.AssertNotNullOrEmpty(threadId, nameof(threadId)); - Argument.AssertNotNullOrEmpty(runId, nameof(runId)); - - using PipelineMessage message = CreateGetRunStepsRequest(threadId, runId, limit, order, after, before, options); - return ClientResult.FromResponse(Pipeline.ProcessMessage(message, options)); - } - - private PipelineMessage CreateGetRunStepsRequest(string threadId, string runId, int? limit, string order, string after, string before, RequestOptions options) - => new AzureOpenAIPipelineMessageBuilder(Pipeline, _endpoint, _apiVersion) - .WithAssistantsHeader() - .WithOptions(options) - .WithMethod("GET") - .WithAccept("application/json") - .WithCommonListParameters(limit, order, after, before) - .WithPath("threads", threadId, "runs", runId, "steps") - .Build(); -} diff --git a/sdk/openai/Azure.AI.OpenAI/src/Custom/Assistants/Internal/Pagination/AzureRunsPageEnumerator.cs b/sdk/openai/Azure.AI.OpenAI/src/Custom/Assistants/Internal/Pagination/AzureRunsPageEnumerator.cs deleted file mode 100644 index 65afbca20db1..000000000000 --- a/sdk/openai/Azure.AI.OpenAI/src/Custom/Assistants/Internal/Pagination/AzureRunsPageEnumerator.cs +++ /dev/null @@ -1,51 +0,0 @@ -// Copyright (c) Microsoft Corporation. All rights reserved. -// Licensed under the MIT License. - -using System.ClientModel; -using System.ClientModel.Primitives; - -namespace Azure.AI.OpenAI.Assistants; - -internal partial class AzureRunsPageEnumerator : RunsPageEnumerator -{ - private readonly Uri _endpoint; - private readonly string _apiVersion; - - public AzureRunsPageEnumerator( - ClientPipeline pipeline, - Uri endpoint, - string threadId, int? limit, string order, string after, string before, - string apiVersion, - RequestOptions options) - : base(pipeline, endpoint, threadId, limit, order, after, before, options) - { - _endpoint = endpoint; - _apiVersion = apiVersion; - } - - internal override async Task GetRunsAsync(string threadId, int? limit, string order, string after, string before, RequestOptions options) - { - Argument.AssertNotNullOrEmpty(threadId, nameof(threadId)); - - using PipelineMessage message = CreateGetRunsRequest(threadId, limit, order, after, before, options); - return ClientResult.FromResponse(await Pipeline.ProcessMessageAsync(message, options).ConfigureAwait(false)); - } - - internal override ClientResult GetRuns(string threadId, int? limit, string order, string after, string before, RequestOptions options) - { - Argument.AssertNotNullOrEmpty(threadId, nameof(threadId)); - - using PipelineMessage message = CreateGetRunsRequest(threadId, limit, order, after, before, options); - return ClientResult.FromResponse(Pipeline.ProcessMessage(message, options)); - } - - private PipelineMessage CreateGetRunsRequest(string threadId, int? limit, string order, string after, string before, RequestOptions options) - => new AzureOpenAIPipelineMessageBuilder(Pipeline, _endpoint, _apiVersion) - .WithAssistantsHeader() - .WithOptions(options) - .WithMethod("GET") - .WithAccept("application/json") - .WithCommonListParameters(limit, order, after, before) - .WithPath("threads", threadId, "runs") - .Build(); -} diff --git a/sdk/openai/Azure.AI.OpenAI/src/Custom/AzureOpenAIClient.cs b/sdk/openai/Azure.AI.OpenAI/src/Custom/AzureOpenAIClient.cs index 7336207a09ca..5a300e2b3211 100644 --- a/sdk/openai/Azure.AI.OpenAI/src/Custom/AzureOpenAIClient.cs +++ b/sdk/openai/Azure.AI.OpenAI/src/Custom/AzureOpenAIClient.cs @@ -122,7 +122,7 @@ public AzureOpenAIClient(Uri endpoint, ApiKeyCredential credential, AzureOpenAIC /// The API key to authenticate with the service. /// The options to configure the client. public AzureOpenAIClient(Uri endpoint, AzureKeyCredential credential, AzureOpenAIClientOptions options) - : this(CreatePipeline(credential?.Key, options), endpoint, options) + : this(CreatePipeline(new ApiKeyCredential(credential?.Key), options), endpoint, options) { } diff --git a/sdk/openai/Azure.AI.OpenAI/src/Custom/AzureOpenAIClientOptions.cs b/sdk/openai/Azure.AI.OpenAI/src/Custom/AzureOpenAIClientOptions.cs index 1b2989bfb2f3..1449e569d398 100644 --- a/sdk/openai/Azure.AI.OpenAI/src/Custom/AzureOpenAIClientOptions.cs +++ b/sdk/openai/Azure.AI.OpenAI/src/Custom/AzureOpenAIClientOptions.cs @@ -56,6 +56,7 @@ public AzureOpenAIClientOptions(ServiceVersion version = LatestVersion) ServiceVersion.V2024_05_01_Preview => "2024-05-01-preview", ServiceVersion.V2024_06_01 => "2024-06-01", ServiceVersion.V2024_07_01_Preview => "2024-07-01-preview", + ServiceVersion.V2024_08_01_Preview => "2024-08-01-preview", _ => throw new NotSupportedException() }; RetryPolicy = new RetryWithDelaysPolicy(); @@ -69,6 +70,7 @@ public enum ServiceVersion V2024_05_01_Preview = 8, V2024_06_01 = 9, V2024_07_01_Preview = 10, + V2024_08_01_Preview = 11, } internal class RetryWithDelaysPolicy : ClientRetryPolicy @@ -99,5 +101,5 @@ protected override TimeSpan GetNextDelay(PipelineMessage message, int tryCount) } } - private const ServiceVersion LatestVersion = ServiceVersion.V2024_07_01_Preview; + private const ServiceVersion LatestVersion = ServiceVersion.V2024_08_01_Preview; } diff --git a/sdk/openai/Azure.AI.OpenAI/src/Custom/AzureTokenAuthenticationPolicy.cs b/sdk/openai/Azure.AI.OpenAI/src/Custom/AzureTokenAuthenticationPolicy.cs index 6fb81cb1a94c..257398df9ed3 100644 --- a/sdk/openai/Azure.AI.OpenAI/src/Custom/AzureTokenAuthenticationPolicy.cs +++ b/sdk/openai/Azure.AI.OpenAI/src/Custom/AzureTokenAuthenticationPolicy.cs @@ -3,6 +3,7 @@ using Azure.Core; using System.ClientModel.Primitives; +using System.Collections.Generic; using System.Net; namespace Azure.AI.OpenAI; diff --git a/sdk/openai/Azure.AI.OpenAI/src/Custom/Batch/AzureBatchClient.Protocol.cs b/sdk/openai/Azure.AI.OpenAI/src/Custom/Batch/AzureBatchClient.Protocol.cs index 00cec454cb27..b417bc85d82e 100644 --- a/sdk/openai/Azure.AI.OpenAI/src/Custom/Batch/AzureBatchClient.Protocol.cs +++ b/sdk/openai/Azure.AI.OpenAI/src/Custom/Batch/AzureBatchClient.Protocol.cs @@ -3,6 +3,7 @@ using System.ClientModel; using System.ClientModel.Primitives; +using Azure.AI.OpenAI.Utility; namespace Azure.AI.OpenAI.Batch; @@ -24,16 +25,25 @@ public override ClientResult CreateBatch(BinaryContent content, RequestOptions o return ClientResult.FromResponse(Pipeline.ProcessMessage(message, options)); } - public override IAsyncEnumerable GetBatchesAsync(string after, int? limit, RequestOptions options) + public override AsyncCollectionResult GetBatchesAsync(string after, int? limit, RequestOptions options) { - BatchesPageEnumerator enumerator = new(Pipeline, _endpoint, after, limit, options); - return PageCollectionHelpers.CreateAsync(enumerator); + return new AzureAsyncCollectionResult( + Pipeline, + options, + continuation => CreateGetBatchesRequest(continuation?.After ?? after, limit, options), + page => BatchCollectionPageToken.FromResponse(page, limit), + page => throw new NotImplementedException("Parsing has not yet been implemented"), + options?.CancellationToken ?? default); } - public override IEnumerable GetBatches(string after, int? limit, RequestOptions options) + public override CollectionResult GetBatches(string after, int? limit, RequestOptions options) { - BatchesPageEnumerator enumerator = new(Pipeline, _endpoint, after, limit, options); - return PageCollectionHelpers.Create(enumerator); + return new AzureCollectionResult( + Pipeline, + options, + continuation => CreateGetBatchesRequest(continuation?.After ?? after, limit, options), + page => BatchCollectionPageToken.FromResponse(page, limit), + page => throw new NotImplementedException("Parsing has not yet been implemented")); } public override async Task GetBatchAsync(string batchId, RequestOptions options) diff --git a/sdk/openai/Azure.AI.OpenAI/src/Custom/Chat/AzureChatClient.cs b/sdk/openai/Azure.AI.OpenAI/src/Custom/Chat/AzureChatClient.cs index 86ca7d229369..036b82e22279 100644 --- a/sdk/openai/Azure.AI.OpenAI/src/Custom/Chat/AzureChatClient.cs +++ b/sdk/openai/Azure.AI.OpenAI/src/Custom/Chat/AzureChatClient.cs @@ -4,6 +4,7 @@ using OpenAI.Chat; using System.ClientModel; using System.ClientModel.Primitives; +using System.Diagnostics.CodeAnalysis; #pragma warning disable AZC0112 @@ -37,19 +38,58 @@ internal AzureChatClient(ClientPipeline pipeline, string deploymentName, Uri end protected AzureChatClient() { } + /// + public override Task> CompleteChatAsync(IEnumerable messages, ChatCompletionOptions options = null, CancellationToken cancellationToken = default) + { + PostfixSwapMaxTokens(ref options); + return base.CompleteChatAsync(messages, options, cancellationToken); + } + + /// + public override ClientResult CompleteChat(IEnumerable messages, ChatCompletionOptions options = null, CancellationToken cancellationToken = default) + { + PostfixSwapMaxTokens(ref options); + return base.CompleteChat(messages, options, cancellationToken); + } + + /// + public override AsyncCollectionResult CompleteChatStreamingAsync(params ChatMessage[] messages) + => CompleteChatStreamingAsync(messages, default(ChatCompletionOptions)); + + /// + public override CollectionResult CompleteChatStreaming(params ChatMessage[] messages) + => CompleteChatStreaming(messages, default(ChatCompletionOptions)); + /// public override AsyncCollectionResult CompleteChatStreamingAsync(IEnumerable messages, ChatCompletionOptions options = null, CancellationToken cancellationToken = default) { - options ??= new(); - options.StreamOptions = null; + PostfixClearStreamOptions(ref options); + PostfixSwapMaxTokens(ref options); return base.CompleteChatStreamingAsync(messages, options, cancellationToken); } /// public override CollectionResult CompleteChatStreaming(IEnumerable messages, ChatCompletionOptions options = null, CancellationToken cancellationToken = default) + { + PostfixClearStreamOptions(ref options); + PostfixSwapMaxTokens(ref options); + return base.CompleteChatStreaming(messages, options, cancellationToken); + } + + private static void PostfixClearStreamOptions(ref ChatCompletionOptions options) { options ??= new(); options.StreamOptions = null; - return base.CompleteChatStreaming(messages, options, cancellationToken); + } + + private static void PostfixSwapMaxTokens(ref ChatCompletionOptions options) + { + options ??= new(); + if (options.MaxOutputTokenCount is not null) + { + options.SerializedAdditionalRawData ??= new Dictionary(); + options.SerializedAdditionalRawData["max_completion_tokens"] = BinaryData.FromObjectAsJson("__EMPTY__"); + options.SerializedAdditionalRawData["max_tokens"] = BinaryData.FromObjectAsJson(options.MaxOutputTokenCount); + } } } diff --git a/sdk/openai/Azure.AI.OpenAI/src/Custom/Chat/AzureChatCompletion.cs b/sdk/openai/Azure.AI.OpenAI/src/Custom/Chat/AzureChatCompletion.cs index 299f2dea3a59..2a66c9fb203b 100644 --- a/sdk/openai/Azure.AI.OpenAI/src/Custom/Chat/AzureChatCompletion.cs +++ b/sdk/openai/Azure.AI.OpenAI/src/Custom/Chat/AzureChatCompletion.cs @@ -8,22 +8,22 @@ #pragma warning disable AZC0112 -namespace Azure.AI.OpenAI; +namespace Azure.AI.OpenAI.Chat; public static partial class AzureChatCompletionExtensions { [Experimental("AOAI001")] - public static ContentFilterResultForPrompt GetContentFilterResultForPrompt(this ChatCompletion chatCompletion) + public static RequestContentFilterResult GetRequestContentFilterResult(this ChatCompletion chatCompletion) { - return AdditionalPropertyHelpers.GetAdditionalListProperty( + return AdditionalPropertyHelpers.GetAdditionalListProperty( chatCompletion.SerializedAdditionalRawData, "prompt_filter_results")?[0]; } [Experimental("AOAI001")] - public static ContentFilterResultForResponse GetContentFilterResultForResponse(this ChatCompletion chatCompletion) + public static ResponseContentFilterResult GetResponseContentFilterResult(this ChatCompletion chatCompletion) { - return AdditionalPropertyHelpers.GetAdditionalProperty( + return AdditionalPropertyHelpers.GetAdditionalProperty( chatCompletion.Choices?[0]?.SerializedAdditionalRawData, "content_filter_results"); } diff --git a/sdk/openai/Azure.AI.OpenAI/src/Custom/Chat/AzureChatCompletionOptions.cs b/sdk/openai/Azure.AI.OpenAI/src/Custom/Chat/AzureChatCompletionOptions.cs index 54ab5606ebbb..0439b9b502a1 100644 --- a/sdk/openai/Azure.AI.OpenAI/src/Custom/Chat/AzureChatCompletionOptions.cs +++ b/sdk/openai/Azure.AI.OpenAI/src/Custom/Chat/AzureChatCompletionOptions.cs @@ -1,11 +1,12 @@ // Copyright (c) Microsoft Corporation. All rights reserved. // Licensed under the MIT License. +using System.Collections.Generic; using System.Diagnostics.CodeAnalysis; using Azure.AI.OpenAI.Chat; using Azure.AI.OpenAI.Internal; -namespace Azure.AI.OpenAI; +namespace Azure.AI.OpenAI.Chat; public static partial class AzureChatCompletionOptionsExtensions { diff --git a/sdk/openai/Azure.AI.OpenAI/src/Custom/Chat/AzureStreamingChatCompletionUpdate.cs b/sdk/openai/Azure.AI.OpenAI/src/Custom/Chat/AzureStreamingChatCompletionUpdate.cs index 9de53f530bc3..c46e4139b26d 100644 --- a/sdk/openai/Azure.AI.OpenAI/src/Custom/Chat/AzureStreamingChatCompletionUpdate.cs +++ b/sdk/openai/Azure.AI.OpenAI/src/Custom/Chat/AzureStreamingChatCompletionUpdate.cs @@ -8,7 +8,7 @@ #pragma warning disable AZC0112 -namespace Azure.AI.OpenAI; +namespace Azure.AI.OpenAI.Chat; public static partial class AzureStreamingChatCompletionUpdateExtensions { @@ -25,17 +25,17 @@ public static AzureChatMessageContext GetAzureMessageContext(this StreamingChatC } [Experimental("AOAI001")] - public static ContentFilterResultForPrompt GetContentFilterResultForPrompt(this StreamingChatCompletionUpdate chatUpdate) + public static RequestContentFilterResult GetRequestContentFilterResult(this StreamingChatCompletionUpdate chatUpdate) { - return AdditionalPropertyHelpers.GetAdditionalListProperty( + return AdditionalPropertyHelpers.GetAdditionalListProperty( chatUpdate.SerializedAdditionalRawData, "prompt_filter_results")?[0]; } [Experimental("AOAI001")] - public static ContentFilterResultForResponse GetContentFilterResultForResponse(this StreamingChatCompletionUpdate chatUpdate) + public static ResponseContentFilterResult GetResponseContentFilterResult(this StreamingChatCompletionUpdate chatUpdate) { - return AdditionalPropertyHelpers.GetAdditionalProperty( + return AdditionalPropertyHelpers.GetAdditionalProperty( chatUpdate?.Choices?.ElementAtOrDefault(0)?.SerializedAdditionalRawData, "content_filter_results"); } diff --git a/sdk/openai/Azure.AI.OpenAI/src/Custom/Chat/Internal/GeneratorStubs.cs b/sdk/openai/Azure.AI.OpenAI/src/Custom/Chat/Internal/GeneratorStubs.cs index 4a2bb2bcdbb4..b64b953326bd 100644 --- a/sdk/openai/Azure.AI.OpenAI/src/Custom/Chat/Internal/GeneratorStubs.cs +++ b/sdk/openai/Azure.AI.OpenAI/src/Custom/Chat/Internal/GeneratorStubs.cs @@ -8,10 +8,12 @@ namespace Azure.AI.OpenAI.Chat; [CodeGenModel("AzureChatDataSourceConnectionStringAuthenticationOptions")] internal partial class InternalAzureChatDataSourceConnectionStringAuthenticationOptions { } [CodeGenModel("AzureChatDataSourceDeploymentNameVectorizationSource")] internal partial class InternalAzureChatDataSourceDeploymentNameVectorizationSource { } [CodeGenModel("AzureChatDataSourceEncodedApiKeyAuthenticationOptions")] internal partial class InternalAzureChatDataSourceEncodedApiKeyAuthenticationOptions { } +[CodeGenModel("AzureChatDataSourceIntegratedVectorizationSource")] internal partial class InternalAzureChatDataSourceIntegratedVectorizationSource { } [CodeGenModel("AzureChatDataSourceKeyAndKeyIdAuthenticationOptions")] internal partial class InternalAzureChatDataSourceKeyAndKeyIdAuthenticationOptions { } [CodeGenModel("AzureChatDataSourceModelIdVectorizationSource")] internal partial class InternalAzureChatDataSourceModelIdVectorizationSource { } [CodeGenModel("AzureChatDataSourceSystemAssignedManagedIdentityAuthenticationOptions")] internal partial class InternalAzureChatDataSourceSystemAssignedManagedIdentityAuthenticationOptions { } [CodeGenModel("AzureChatDataSourceUserAssignedManagedIdentityAuthenticationOptions")] internal partial class InternalAzureChatDataSourceUserAssignedManagedIdentityAuthenticationOptions { } +[CodeGenModel("AzureChatDataSourceUsernameAndPasswordAuthenticationOptions")] internal partial class InternalAzureChatDataSourceUsernameAndPasswordAuthenticationOptions { } [CodeGenModel("AzureSearchChatDataSourceParametersIncludeContext")] internal readonly partial struct InternalAzureSearchChatDataSourceParametersIncludeContext { } [CodeGenModel("UnknownAzureChatDataSource")] internal partial class InternalUnknownAzureChatDataSource { } [CodeGenModel("UnknownAzureChatDataSourceAuthenticationOptions")] internal partial class InternalUnknownAzureChatDataSourceAuthenticationOptions { } diff --git a/sdk/openai/Azure.AI.OpenAI/src/Custom/Chat/Internal/InternalAzureCosmosDBChatDataSourceParameters.cs b/sdk/openai/Azure.AI.OpenAI/src/Custom/Chat/Internal/InternalAzureCosmosDBChatDataSourceParameters.cs index a3a7a1bc3d93..22d2e7428848 100644 --- a/sdk/openai/Azure.AI.OpenAI/src/Custom/Chat/Internal/InternalAzureCosmosDBChatDataSourceParameters.cs +++ b/sdk/openai/Azure.AI.OpenAI/src/Custom/Chat/Internal/InternalAzureCosmosDBChatDataSourceParameters.cs @@ -1,6 +1,8 @@ // Copyright (c) Microsoft Corporation. All rights reserved. // Licensed under the MIT License. +using System.Collections.Generic; + namespace Azure.AI.OpenAI.Chat; [CodeGenModel("AzureCosmosDBChatDataSourceParameters")] @@ -8,10 +10,10 @@ internal partial class InternalAzureCosmosDBChatDataSourceParameters { [CodeGenMember("IncludeContexts")] private IList _internalIncludeContexts = new ChangeTrackingList(); - private DataSourceOutputContextFlags? _outputContextFlags; + private DataSourceOutputContexts? _outputContextFlags; - /// - public DataSourceOutputContextFlags? OutputContextFlags + /// + public DataSourceOutputContexts? OutputContextFlags { get => DataSourceOutputContextFlagsExtensions.FromStringList(_internalIncludeContexts); internal set diff --git a/sdk/openai/Azure.AI.OpenAI/src/Custom/Chat/Internal/InternalAzureMachineLearningIndexDataSourceParameters.cs b/sdk/openai/Azure.AI.OpenAI/src/Custom/Chat/Internal/InternalAzureMachineLearningIndexDataSourceParameters.cs deleted file mode 100644 index 07930fab628d..000000000000 --- a/sdk/openai/Azure.AI.OpenAI/src/Custom/Chat/Internal/InternalAzureMachineLearningIndexDataSourceParameters.cs +++ /dev/null @@ -1,37 +0,0 @@ -// Copyright (c) Microsoft Corporation. All rights reserved. -// Licensed under the MIT License. - -namespace Azure.AI.OpenAI.Chat; - -[CodeGenModel("AzureMachineLearningIndexChatDataSourceParameters")] -internal partial class InternalAzureMachineLearningIndexChatDataSourceParameters -{ - [CodeGenMember("IncludeContexts")] - private IList _internalIncludeContexts = new ChangeTrackingList(); - private DataSourceOutputContextFlags? _outputContextFlags; - - /// - public DataSourceOutputContextFlags? OutputContextFlags - { - get => DataSourceOutputContextFlagsExtensions.FromStringList(_internalIncludeContexts); - internal set - { - _outputContextFlags = value; - _internalIncludeContexts = _outputContextFlags?.ToStringList(); - } - } - - /// - /// The authentication options to use with the Azure Machine Learning Index data source. - /// - /// - /// Azure Machine Learning Index data sources support any of the following options: - /// - /// - /// - /// - /// - /// - [CodeGenMember("Authentication")] - public DataSourceAuthentication Authentication { get; set; } -} diff --git a/sdk/openai/Azure.AI.OpenAI/src/Custom/Chat/Internal/InternalAzureSearchChatDataSourceParameters.cs b/sdk/openai/Azure.AI.OpenAI/src/Custom/Chat/Internal/InternalAzureSearchChatDataSourceParameters.cs index a8cc7c74f256..a098adb9bfda 100644 --- a/sdk/openai/Azure.AI.OpenAI/src/Custom/Chat/Internal/InternalAzureSearchChatDataSourceParameters.cs +++ b/sdk/openai/Azure.AI.OpenAI/src/Custom/Chat/Internal/InternalAzureSearchChatDataSourceParameters.cs @@ -1,6 +1,8 @@ // Copyright (c) Microsoft Corporation. All rights reserved. // Licensed under the MIT License. +using System.Collections.Generic; + namespace Azure.AI.OpenAI.Chat; [CodeGenModel("AzureSearchChatDataSourceParameters")] @@ -8,10 +10,10 @@ internal partial class InternalAzureSearchChatDataSourceParameters { [CodeGenMember("IncludeContexts")] private IList _internalIncludeContexts = new ChangeTrackingList(); - private DataSourceOutputContextFlags? _outputContextFlags; + private DataSourceOutputContexts? _outputContextFlags; - /// - public DataSourceOutputContextFlags? OutputContextFlags + /// + public DataSourceOutputContexts? OutputContextFlags { get => DataSourceOutputContextFlagsExtensions.FromStringList(_internalIncludeContexts); internal set diff --git a/sdk/openai/Azure.AI.OpenAI/src/Custom/Chat/Internal/InternalElasticsearchChatDataSourceParameters.cs b/sdk/openai/Azure.AI.OpenAI/src/Custom/Chat/Internal/InternalElasticsearchChatDataSourceParameters.cs index 568067e4c9c9..44510410ab54 100644 --- a/sdk/openai/Azure.AI.OpenAI/src/Custom/Chat/Internal/InternalElasticsearchChatDataSourceParameters.cs +++ b/sdk/openai/Azure.AI.OpenAI/src/Custom/Chat/Internal/InternalElasticsearchChatDataSourceParameters.cs @@ -1,6 +1,8 @@ // Copyright (c) Microsoft Corporation. All rights reserved. // Licensed under the MIT License. +using System.Collections.Generic; + namespace Azure.AI.OpenAI.Chat; [CodeGenModel("ElasticsearchChatDataSourceParameters")] @@ -8,10 +10,10 @@ internal partial class InternalElasticsearchChatDataSourceParameters { [CodeGenMember("IncludeContexts")] private IList _internalIncludeContexts = new ChangeTrackingList(); - private DataSourceOutputContextFlags? _outputContextFlags; + private DataSourceOutputContexts? _outputContextFlags; - /// - public DataSourceOutputContextFlags? OutputContextFlags + /// + public DataSourceOutputContexts? OutputContextFlags { get => DataSourceOutputContextFlagsExtensions.FromStringList(_internalIncludeContexts); internal set diff --git a/sdk/openai/Azure.AI.OpenAI/src/Custom/Chat/Internal/InternalMongoDBChatDataSourceParameters.cs b/sdk/openai/Azure.AI.OpenAI/src/Custom/Chat/Internal/InternalMongoDBChatDataSourceParameters.cs new file mode 100644 index 000000000000..0798912657b6 --- /dev/null +++ b/sdk/openai/Azure.AI.OpenAI/src/Custom/Chat/Internal/InternalMongoDBChatDataSourceParameters.cs @@ -0,0 +1,64 @@ +// Copyright (c) Microsoft Corporation. All rights reserved. +// Licensed under the MIT License. + +using System.Collections.Generic; + +namespace Azure.AI.OpenAI.Chat; + +[CodeGenModel("MongoDBChatDataSourceParameters")] +internal partial class InternalMongoDBChatDataSourceParameters +{ + [CodeGenMember("IncludeContexts")] + private IList _internalIncludeContexts = new ChangeTrackingList(); + private DataSourceOutputContexts? _outputContextFlags; + + /// + public DataSourceOutputContexts? OutputContextFlags + { + get => DataSourceOutputContextFlagsExtensions.FromStringList(_internalIncludeContexts); + internal set + { + _outputContextFlags = value; + _internalIncludeContexts = _outputContextFlags?.ToStringList(); + } + } + + /// The index field mappings. This is required for MongoDB data sources. + /// + /// Supported field mappings for MongoDB data sources include: + /// + /// -- Required + /// + /// + /// + /// + /// + /// + [CodeGenMember("FieldsMapping")] + public DataSourceFieldMappings FieldMappings { get; set; } + + /// + /// The authentication options to use with the MongoDB data source. + /// + /// + /// MongoDB data sources support any of the following options: + /// + /// + /// + /// + [CodeGenMember("Authentication")] + public DataSourceAuthentication Authentication { get; set; } + + /// + /// The vectorization dependency used for embeddings. + /// + /// + /// Supported vectorization dependencies for Azure Search data sources include: + /// + /// + /// + /// + /// + [CodeGenMember("EmbeddingDependency")] + public DataSourceVectorizer EmbeddingDependency { get; set; } +} diff --git a/sdk/openai/Azure.AI.OpenAI/src/Custom/Chat/Internal/InternalPineconeChatDataSourceParameters.cs b/sdk/openai/Azure.AI.OpenAI/src/Custom/Chat/Internal/InternalPineconeChatDataSourceParameters.cs index 3b9288b153e3..4d222d70e7e5 100644 --- a/sdk/openai/Azure.AI.OpenAI/src/Custom/Chat/Internal/InternalPineconeChatDataSourceParameters.cs +++ b/sdk/openai/Azure.AI.OpenAI/src/Custom/Chat/Internal/InternalPineconeChatDataSourceParameters.cs @@ -1,6 +1,8 @@ // Copyright (c) Microsoft Corporation. All rights reserved. // Licensed under the MIT License. +using System.Collections.Generic; + namespace Azure.AI.OpenAI.Chat; [CodeGenModel("PineconeChatDataSourceParameters")] @@ -8,10 +10,10 @@ internal partial class InternalPineconeChatDataSourceParameters { [CodeGenMember("IncludeContexts")] private IList _internalIncludeContexts = new ChangeTrackingList(); - private DataSourceOutputContextFlags? _outputContextFlags; + private DataSourceOutputContexts? _outputContextFlags; - /// - public DataSourceOutputContextFlags? OutputContextFlags + /// + public DataSourceOutputContexts? OutputContextFlags { get => DataSourceOutputContextFlagsExtensions.FromStringList(_internalIncludeContexts); internal set diff --git a/sdk/openai/Azure.AI.OpenAI/src/Custom/Chat/OnYourData/AzureCosmosDBChatDataSource.cs b/sdk/openai/Azure.AI.OpenAI/src/Custom/Chat/OnYourData/AzureCosmosDBChatDataSource.cs index 9f3933cdec69..89b2fb5920ff 100644 --- a/sdk/openai/Azure.AI.OpenAI/src/Custom/Chat/OnYourData/AzureCosmosDBChatDataSource.cs +++ b/sdk/openai/Azure.AI.OpenAI/src/Custom/Chat/OnYourData/AzureCosmosDBChatDataSource.cs @@ -1,6 +1,8 @@ // Copyright (c) Microsoft Corporation. All rights reserved. // Licensed under the MIT License. +using System; +using System.Collections.Generic; using System.Diagnostics.CodeAnalysis; namespace Azure.AI.OpenAI.Chat; @@ -15,91 +17,84 @@ public partial class AzureCosmosDBChatDataSource : AzureChatDataSource required public string ContainerName { get => InternalParameters.ContainerName; - init => InternalParameters.ContainerName = value; + set => InternalParameters.ContainerName = value; } /// required public string DatabaseName { get => InternalParameters.DatabaseName; - init => InternalParameters.DatabaseName = value; + set => InternalParameters.DatabaseName = value; } /// required public string IndexName { get => InternalParameters.IndexName; - init => InternalParameters.IndexName = value; + set => InternalParameters.IndexName = value; } /// required public DataSourceAuthentication Authentication { get => InternalParameters.Authentication; - init => InternalParameters.Authentication = value; + set => InternalParameters.Authentication = value; } /// required public DataSourceVectorizer VectorizationSource { get => InternalParameters.VectorizationSource; - init => InternalParameters.VectorizationSource = value; + set => InternalParameters.VectorizationSource = value; } /// required public DataSourceFieldMappings FieldMappings { get => InternalParameters.FieldMappings; - init => InternalParameters.FieldMappings = value; + set => InternalParameters.FieldMappings = value; } /// public int? TopNDocuments { get => InternalParameters.TopNDocuments; - init => InternalParameters.TopNDocuments = value; + set => InternalParameters.TopNDocuments = value; } /// public bool? InScope { get => InternalParameters.InScope; - init => InternalParameters.InScope = value; + set => InternalParameters.InScope = value; } /// public int? Strictness { get => InternalParameters.Strictness; - init => InternalParameters.Strictness = value; - } - - /// - public string RoleInformation - { - get => InternalParameters.RoleInformation; - init => InternalParameters.RoleInformation = value; + set => InternalParameters.Strictness = value; } /// public int? MaxSearchQueries { get => InternalParameters.MaxSearchQueries; - init => InternalParameters.MaxSearchQueries = value; + set => InternalParameters.MaxSearchQueries = value; } /// public bool? AllowPartialResult { get => InternalParameters.AllowPartialResult; - init => InternalParameters.AllowPartialResult = value; + set => InternalParameters.AllowPartialResult = value; } /// - public DataSourceOutputContextFlags? OutputContextFlags + public DataSourceOutputContexts? OutputContextFlags { get => InternalParameters.OutputContextFlags; - init => InternalParameters.OutputContextFlags = value; + set => InternalParameters.OutputContextFlags = value; } /// diff --git a/sdk/openai/Azure.AI.OpenAI/src/Custom/Chat/OnYourData/AzureMachineLearningIndexChatDataSource.cs b/sdk/openai/Azure.AI.OpenAI/src/Custom/Chat/OnYourData/AzureMachineLearningIndexChatDataSource.cs deleted file mode 100644 index cd0550e0fa91..000000000000 --- a/sdk/openai/Azure.AI.OpenAI/src/Custom/Chat/OnYourData/AzureMachineLearningIndexChatDataSource.cs +++ /dev/null @@ -1,126 +0,0 @@ -// Copyright (c) Microsoft Corporation. All rights reserved. -// Licensed under the MIT License. - -using System.Diagnostics.CodeAnalysis; - -namespace Azure.AI.OpenAI.Chat; - -[CodeGenModel("AzureMachineLearningIndexChatDataSource")] -public partial class AzureMachineLearningIndexChatDataSource : AzureChatDataSource -{ - [CodeGenMember("Parameters")] - internal InternalAzureMachineLearningIndexChatDataSourceParameters InternalParameters { get; } - - /// - required public string IndexName - { - get => InternalParameters.Name; - init => InternalParameters.Name = value; - } - - /// - required public string ProjectResourceId - { - get => InternalParameters.ProjectResourceId; - init => InternalParameters.ProjectResourceId = value; - } - - /// - required public DataSourceAuthentication Authentication - { - get => InternalParameters.Authentication; - init => InternalParameters.Authentication = value; - } - - /// - required public string Version - { - get => InternalParameters.Version; - init => InternalParameters.Version = value; - } - - /// - public int? TopNDocuments - { - get => InternalParameters.TopNDocuments; - init => InternalParameters.TopNDocuments = value; - } - - /// - public bool? InScope - { - get => InternalParameters.InScope; - init => InternalParameters.InScope = value; - } - - /// - public int? Strictness - { - get => InternalParameters.Strictness; - init => InternalParameters.Strictness = value; - } - - /// - public string RoleInformation - { - get => InternalParameters.RoleInformation; - init => InternalParameters.RoleInformation = value; - } - - /// - public int? MaxSearchQueries - { - get => InternalParameters.MaxSearchQueries; - init => InternalParameters.MaxSearchQueries = value; - } - - /// - public bool? AllowPartialResult - { - get => InternalParameters.AllowPartialResult; - init => InternalParameters.AllowPartialResult = value; - } - - /// - public DataSourceOutputContextFlags? OutputContextFlags - { - get => InternalParameters.OutputContextFlags; - init => InternalParameters.OutputContextFlags = value; - } - - /// - public string Filter - { - get => InternalParameters.Filter; - init => InternalParameters.Filter = value; - } - - /// - /// Creates a new instance of . - /// - public AzureMachineLearningIndexChatDataSource() : base(type: "azure_ml_index", serializedAdditionalRawData: null) - { - InternalParameters = new(); - } - - // CUSTOM: Made internal. - /// Initializes a new instance of . - /// The parameter information to control the use of the Azure Machine Learning Index data source. - /// is null. - internal AzureMachineLearningIndexChatDataSource(InternalAzureMachineLearningIndexChatDataSourceParameters internalParameters) - { - Argument.AssertNotNull(internalParameters, nameof(internalParameters)); - InternalParameters = internalParameters; - } - - /// Initializes a new instance of . - /// - /// Keeps track of any properties unknown to the library. - /// The parameter information to control the use of the Azure Search data source. - [SetsRequiredMembers] - internal AzureMachineLearningIndexChatDataSource(string type, IDictionary serializedAdditionalRawData, InternalAzureMachineLearningIndexChatDataSourceParameters internalParameters) - : base(type, serializedAdditionalRawData) - { - InternalParameters = internalParameters; - } -} diff --git a/sdk/openai/Azure.AI.OpenAI/src/Custom/Chat/OnYourData/AzureSearchChatDataSource.cs b/sdk/openai/Azure.AI.OpenAI/src/Custom/Chat/OnYourData/AzureSearchChatDataSource.cs index 799cc13dc82d..d3952ff5283f 100644 --- a/sdk/openai/Azure.AI.OpenAI/src/Custom/Chat/OnYourData/AzureSearchChatDataSource.cs +++ b/sdk/openai/Azure.AI.OpenAI/src/Custom/Chat/OnYourData/AzureSearchChatDataSource.cs @@ -1,6 +1,8 @@ // Copyright (c) Microsoft Corporation. All rights reserved. // Licensed under the MIT License. +using System; +using System.Collections.Generic; using System.Diagnostics.CodeAnalysis; namespace Azure.AI.OpenAI.Chat; @@ -15,105 +17,98 @@ public partial class AzureSearchChatDataSource : AzureChatDataSource required public Uri Endpoint { get => InternalParameters.Endpoint; - init => InternalParameters.Endpoint = value; + set => InternalParameters.Endpoint = value; } /// required public string IndexName { get => InternalParameters.IndexName; - init => InternalParameters.IndexName = value; + set => InternalParameters.IndexName = value; } /// required public DataSourceAuthentication Authentication { get => InternalParameters.Authentication; - init => InternalParameters.Authentication = value; + set => InternalParameters.Authentication = value; } /// public int? TopNDocuments { get => InternalParameters.TopNDocuments; - init => InternalParameters.TopNDocuments = value; + set => InternalParameters.TopNDocuments = value; } /// public bool? InScope { get => InternalParameters.InScope; - init => InternalParameters.InScope = value; + set => InternalParameters.InScope = value; } /// public int? Strictness { get => InternalParameters.Strictness; - init => InternalParameters.Strictness = value; - } - - /// - public string RoleInformation - { - get => InternalParameters.RoleInformation; - init => InternalParameters.RoleInformation = value; + set => InternalParameters.Strictness = value; } /// public int? MaxSearchQueries { get => InternalParameters.MaxSearchQueries; - init => InternalParameters.MaxSearchQueries = value; + set => InternalParameters.MaxSearchQueries = value; } /// public bool? AllowPartialResult { get => InternalParameters.AllowPartialResult; - init => InternalParameters.AllowPartialResult = value; + set => InternalParameters.AllowPartialResult = value; } /// - public DataSourceOutputContextFlags? OutputContextFlags + public DataSourceOutputContexts? OutputContextFlags { get => InternalParameters.OutputContextFlags; - init => InternalParameters.OutputContextFlags = value; + set => InternalParameters.OutputContextFlags = value; } /// public DataSourceFieldMappings FieldMappings { get => InternalParameters.FieldMappings; - init => InternalParameters.FieldMappings = value; + set => InternalParameters.FieldMappings = value; } /// public DataSourceQueryType? QueryType { get => InternalParameters.QueryType; - init => InternalParameters.QueryType = value; + set => InternalParameters.QueryType = value; } /// public string SemanticConfiguration { get => InternalParameters.SemanticConfiguration; - init => InternalParameters.SemanticConfiguration = value; + set => InternalParameters.SemanticConfiguration = value; } /// public string Filter { get => InternalParameters.Filter; - init => InternalParameters.Filter = value; + set => InternalParameters.Filter = value; } /// public DataSourceVectorizer VectorizationSource { get => InternalParameters.VectorizationSource; - init => InternalParameters.VectorizationSource = value; + set => InternalParameters.VectorizationSource = value; } /// diff --git a/sdk/openai/Azure.AI.OpenAI/src/Custom/Chat/OnYourData/DataSourceAuthentication.cs b/sdk/openai/Azure.AI.OpenAI/src/Custom/Chat/OnYourData/DataSourceAuthentication.cs index 070b79547df6..f9cac287b985 100644 --- a/sdk/openai/Azure.AI.OpenAI/src/Custom/Chat/OnYourData/DataSourceAuthentication.cs +++ b/sdk/openai/Azure.AI.OpenAI/src/Custom/Chat/OnYourData/DataSourceAuthentication.cs @@ -8,6 +8,8 @@ public partial class DataSourceAuthentication { public static DataSourceAuthentication FromApiKey(string apiKey) => new InternalAzureChatDataSourceApiKeyAuthenticationOptions(apiKey); + public static DataSourceAuthentication FromUsernameAndPassword(string username, string password) + => new InternalAzureChatDataSourceUsernameAndPasswordAuthenticationOptions(username, password); public static DataSourceAuthentication FromAccessToken(string accessToken) => new InternalAzureChatDataSourceAccessTokenAuthenticationOptions(accessToken); public static DataSourceAuthentication FromConnectionString(string connectionString) diff --git a/sdk/openai/Azure.AI.OpenAI/src/Custom/Chat/OnYourData/DataSourceFieldMappings.cs b/sdk/openai/Azure.AI.OpenAI/src/Custom/Chat/OnYourData/DataSourceFieldMappings.cs index 999ade6bcc5b..94bdb592287f 100644 --- a/sdk/openai/Azure.AI.OpenAI/src/Custom/Chat/OnYourData/DataSourceFieldMappings.cs +++ b/sdk/openai/Azure.AI.OpenAI/src/Custom/Chat/OnYourData/DataSourceFieldMappings.cs @@ -1,6 +1,8 @@ // Copyright (c) Microsoft Corporation. All rights reserved. // Licensed under the MIT License. +using System.Collections.Generic; + namespace Azure.AI.OpenAI.Chat; [CodeGenModel("AzureSearchChatDataSourceParametersFieldsMapping")] @@ -10,7 +12,7 @@ public partial class DataSourceFieldMappings /// The name of the index field to use as a title. /// [CodeGenMember("TitleField")] - public string TitleFieldName { get; init;} + public string TitleFieldName { get; set;} /// /// The name of the index field to use as a URL. @@ -21,12 +23,9 @@ public partial class DataSourceFieldMappings /// , , and /// . /// - /// - /// It is not applicable to types including: . - /// /// [CodeGenMember("UrlField")] - public string UrlFieldName { get; init;} + public string UrlFieldName { get; set;} /// The name of the index field to use as a filepath. /// @@ -35,12 +34,9 @@ public partial class DataSourceFieldMappings /// , , and /// . /// - /// - /// It is not applicable to types including: . - /// /// [CodeGenMember("FilepathField")] - public string FilepathFieldName { get; init; } + public string FilepathFieldName { get; set; } /// The names of index fields that should be treated as content. /// @@ -49,9 +45,6 @@ public partial class DataSourceFieldMappings /// , , and /// . /// - /// - /// It is not applicable to types including: . - /// /// [CodeGenMember("ContentFields")] public IList ContentFieldNames { get; } = new ChangeTrackingList(); @@ -63,12 +56,9 @@ public partial class DataSourceFieldMappings /// , , and /// . /// - /// - /// It is not applicable to types including: . - /// /// [CodeGenMember("ContentFieldsSeparator")] - public string ContentFieldSeparator { get; init;} + public string ContentFieldSeparator { get; set;} /// The names of fields that represent vector data. /// @@ -77,8 +67,7 @@ public partial class DataSourceFieldMappings /// , and . /// /// - /// It is not applicable to types including: and - /// . + /// It is not applicable to types including: . /// /// [CodeGenMember("VectorFields")] diff --git a/sdk/openai/Azure.AI.OpenAI/src/Custom/Chat/OnYourData/DataSourceOutputContextFlags.Serialization.cs b/sdk/openai/Azure.AI.OpenAI/src/Custom/Chat/OnYourData/DataSourceOutputContexts.Serialization.cs similarity index 61% rename from sdk/openai/Azure.AI.OpenAI/src/Custom/Chat/OnYourData/DataSourceOutputContextFlags.Serialization.cs rename to sdk/openai/Azure.AI.OpenAI/src/Custom/Chat/OnYourData/DataSourceOutputContexts.Serialization.cs index b5a0ff12d99c..9ffa55768502 100644 --- a/sdk/openai/Azure.AI.OpenAI/src/Custom/Chat/OnYourData/DataSourceOutputContextFlags.Serialization.cs +++ b/sdk/openai/Azure.AI.OpenAI/src/Custom/Chat/OnYourData/DataSourceOutputContexts.Serialization.cs @@ -1,48 +1,50 @@ // Copyright (c) Microsoft Corporation. All rights reserved. // Licensed under the MIT License. +using System.Collections.Generic; + namespace Azure.AI.OpenAI.Chat; internal static partial class DataSourceOutputContextFlagsExtensions { - public static IList ToStringList(this DataSourceOutputContextFlags flags) + public static IList ToStringList(this DataSourceOutputContexts flags) { List contexts = []; - if (flags.HasFlag(DataSourceOutputContextFlags.Intent)) + if (flags.HasFlag(DataSourceOutputContexts.Intent)) { contexts.Add("intent"); } - if (flags.HasFlag(DataSourceOutputContextFlags.Citations)) + if (flags.HasFlag(DataSourceOutputContexts.Citations)) { contexts.Add("citations"); } - if (flags.HasFlag(DataSourceOutputContextFlags.AllRetrievedDocuments)) + if (flags.HasFlag(DataSourceOutputContexts.AllRetrievedDocuments)) { contexts.Add("all_retrieved_documents"); } return contexts; } - public static DataSourceOutputContextFlags? FromStringList(IList strings) + public static DataSourceOutputContexts? FromStringList(IList strings) { if (strings is null) { return null; } - DataSourceOutputContextFlags flags = 0; + DataSourceOutputContexts flags = 0; foreach (string s in strings) { if (s == "citations") { - flags |= DataSourceOutputContextFlags.Citations; + flags |= DataSourceOutputContexts.Citations; } else if (s == "intent") { - flags |= DataSourceOutputContextFlags.Intent; + flags |= DataSourceOutputContexts.Intent; } else if (s == "all_retrieved_documents") { - flags |= DataSourceOutputContextFlags.AllRetrievedDocuments; + flags |= DataSourceOutputContexts.AllRetrievedDocuments; } } return flags; diff --git a/sdk/openai/Azure.AI.OpenAI/src/Custom/Chat/OnYourData/DataSourceOutputContextFlags.cs b/sdk/openai/Azure.AI.OpenAI/src/Custom/Chat/OnYourData/DataSourceOutputContexts.cs similarity index 81% rename from sdk/openai/Azure.AI.OpenAI/src/Custom/Chat/OnYourData/DataSourceOutputContextFlags.cs rename to sdk/openai/Azure.AI.OpenAI/src/Custom/Chat/OnYourData/DataSourceOutputContexts.cs index 1123f96f78ed..826fd033764f 100644 --- a/sdk/openai/Azure.AI.OpenAI/src/Custom/Chat/OnYourData/DataSourceOutputContextFlags.cs +++ b/sdk/openai/Azure.AI.OpenAI/src/Custom/Chat/OnYourData/DataSourceOutputContexts.cs @@ -12,11 +12,11 @@ namespace Azure.AI.OpenAI.Chat; /// /// This value is provided as a bitmask flag. For example, to request intent and all_retrieved_documents /// contexts, use the bitwise OR operator by assigning -/// | . +/// | . /// /// [Flags] -public enum DataSourceOutputContextFlags : int +public enum DataSourceOutputContexts : int { Intent = 1 << 0, Citations = 1 << 1, diff --git a/sdk/openai/Azure.AI.OpenAI/src/Custom/Chat/OnYourData/DataSourceVectorizer.cs b/sdk/openai/Azure.AI.OpenAI/src/Custom/Chat/OnYourData/DataSourceVectorizer.cs index 51e4847b35ee..82f44ab176fe 100644 --- a/sdk/openai/Azure.AI.OpenAI/src/Custom/Chat/OnYourData/DataSourceVectorizer.cs +++ b/sdk/openai/Azure.AI.OpenAI/src/Custom/Chat/OnYourData/DataSourceVectorizer.cs @@ -23,4 +23,6 @@ public static DataSourceVectorizer FromDeploymentName(string deploymentName) => new InternalAzureChatDataSourceDeploymentNameVectorizationSource(deploymentName); public static DataSourceVectorizer FromModelId(string modelId) => new InternalAzureChatDataSourceModelIdVectorizationSource(modelId); + public static DataSourceVectorizer FromIntegratedResource() + => new InternalAzureChatDataSourceIntegratedVectorizationSource(); } diff --git a/sdk/openai/Azure.AI.OpenAI/src/Custom/Chat/OnYourData/ElasticsearchChatDataSource.cs b/sdk/openai/Azure.AI.OpenAI/src/Custom/Chat/OnYourData/ElasticsearchChatDataSource.cs index 8ded23802340..28c3c9781b32 100644 --- a/sdk/openai/Azure.AI.OpenAI/src/Custom/Chat/OnYourData/ElasticsearchChatDataSource.cs +++ b/sdk/openai/Azure.AI.OpenAI/src/Custom/Chat/OnYourData/ElasticsearchChatDataSource.cs @@ -1,6 +1,8 @@ // Copyright (c) Microsoft Corporation. All rights reserved. // Licensed under the MIT License. +using System; +using System.Collections.Generic; using System.Diagnostics.CodeAnalysis; namespace Azure.AI.OpenAI.Chat; @@ -15,91 +17,84 @@ public partial class ElasticsearchChatDataSource : AzureChatDataSource required public Uri Endpoint { get => InternalParameters.Endpoint; - init => InternalParameters.Endpoint = value; + set => InternalParameters.Endpoint = value; } /// required public string IndexName { get => InternalParameters.IndexName; - init => InternalParameters.IndexName = value; + set => InternalParameters.IndexName = value; } /// required public DataSourceAuthentication Authentication { get => InternalParameters.Authentication; - init => InternalParameters.Authentication = value; + set => InternalParameters.Authentication = value; } /// public int? TopNDocuments { get => InternalParameters.TopNDocuments; - init => InternalParameters.TopNDocuments = value; + set => InternalParameters.TopNDocuments = value; } /// public bool? InScope { get => InternalParameters.InScope; - init => InternalParameters.InScope = value; + set => InternalParameters.InScope = value; } /// public int? Strictness { get => InternalParameters.Strictness; - init => InternalParameters.Strictness = value; - } - - /// - public string RoleInformation - { - get => InternalParameters.RoleInformation; - init => InternalParameters.RoleInformation = value; + set => InternalParameters.Strictness = value; } /// public int? MaxSearchQueries { get => InternalParameters.MaxSearchQueries; - init => InternalParameters.MaxSearchQueries = value; + set => InternalParameters.MaxSearchQueries = value; } /// public bool? AllowPartialResult { get => InternalParameters.AllowPartialResult; - init => InternalParameters.AllowPartialResult = value; + set => InternalParameters.AllowPartialResult = value; } /// - public DataSourceOutputContextFlags? OutputContextFlags + public DataSourceOutputContexts? OutputContextFlags { get => InternalParameters.OutputContextFlags; - init => InternalParameters.OutputContextFlags = value; + set => InternalParameters.OutputContextFlags = value; } /// public DataSourceFieldMappings FieldMappings { get => InternalParameters.FieldMappings; - init => InternalParameters.FieldMappings = value; + set => InternalParameters.FieldMappings = value; } /// public DataSourceQueryType? QueryType { get => InternalParameters.QueryType; - init => InternalParameters.QueryType = value; + set => InternalParameters.QueryType = value; } /// public DataSourceVectorizer VectorizationSource { get => InternalParameters.VectorizationSource; - init => InternalParameters.VectorizationSource = value; + set => InternalParameters.VectorizationSource = value; } public ElasticsearchChatDataSource() : base(type: "elasticsearch", serializedAdditionalRawData: null) diff --git a/sdk/openai/Azure.AI.OpenAI/src/Custom/Chat/OnYourData/MongoDBChatDataSource.cs b/sdk/openai/Azure.AI.OpenAI/src/Custom/Chat/OnYourData/MongoDBChatDataSource.cs new file mode 100644 index 000000000000..ec8b4983e0ae --- /dev/null +++ b/sdk/openai/Azure.AI.OpenAI/src/Custom/Chat/OnYourData/MongoDBChatDataSource.cs @@ -0,0 +1,128 @@ +// Copyright (c) Microsoft Corporation. All rights reserved. +// Licensed under the MIT License. + +using System; +using System.Collections.Generic; +using System.Diagnostics.CodeAnalysis; + +namespace Azure.AI.OpenAI.Chat; + +[CodeGenModel("MongoDBChatDataSource")] +public partial class MongoDBChatDataSource : AzureChatDataSource +{ + [CodeGenMember("Parameters")] + internal InternalMongoDBChatDataSourceParameters InternalParameters { get; } + + /// + required public DataSourceAuthentication Authentication + { + get => InternalParameters.Authentication; + set => InternalParameters.Authentication = value; + } + + /// + required public string EndpointName + { + get => InternalParameters.Endpoint; + set => InternalParameters.Endpoint = value; + } + + /// + required public string CollectionName + { + get => InternalParameters.CollectionName; + set => InternalParameters.CollectionName = value; + } + + /// + required public string AppName + { + get => InternalParameters.AppName; + set => InternalParameters.AppName = value; + } + + /// + required public string IndexName + { + get => InternalParameters.IndexName; + set => InternalParameters.IndexName = value; + } + + /// + public int? TopNDocuments + { + get => InternalParameters.TopNDocuments; + set => InternalParameters.TopNDocuments = value; + } + + /// + public bool? InScope + { + get => InternalParameters.InScope; + set => InternalParameters.InScope = value; + } + + /// + public int? Strictness + { + get => InternalParameters.Strictness; + set => InternalParameters.Strictness = value; + } + + /// + public int? MaxSearchQueries + { + get => InternalParameters.MaxSearchQueries; + set => InternalParameters.MaxSearchQueries = value; + } + + /// + public bool? AllowPartialResult + { + get => InternalParameters.AllowPartialResult; + set => InternalParameters.AllowPartialResult = value; + } + + /// + public DataSourceOutputContexts? OutputContextFlags + { + get => InternalParameters.OutputContextFlags; + set => InternalParameters.OutputContextFlags = value; + } + + /// + public DataSourceVectorizer VectorizationSource + { + get => InternalParameters.EmbeddingDependency; + set => InternalParameters.EmbeddingDependency = value; + } + + /// + /// Creates a new instance of . + /// + public MongoDBChatDataSource() : base(type: "mongo_db", serializedAdditionalRawData: null) + { + InternalParameters = new(); + } + + // CUSTOM: Made internal. + /// Initializes a new instance of . + /// The parameter information to control the use of the MongoDB data source. + /// is null. + internal MongoDBChatDataSource(InternalMongoDBChatDataSourceParameters internalParameters) + { + Argument.AssertNotNull(internalParameters, nameof(internalParameters)); + InternalParameters = internalParameters; + } + + /// Initializes a new instance of . + /// + /// Keeps track of any properties unknown to the library. + /// The parameter information to control the use of the Azure Search data source. + [SetsRequiredMembers] + internal MongoDBChatDataSource(string type, IDictionary serializedAdditionalRawData, InternalMongoDBChatDataSourceParameters internalParameters) + : base(type, serializedAdditionalRawData) + { + InternalParameters = internalParameters; + } +} diff --git a/sdk/openai/Azure.AI.OpenAI/src/Custom/Chat/OnYourData/PineconeChatDataSource.cs b/sdk/openai/Azure.AI.OpenAI/src/Custom/Chat/OnYourData/PineconeChatDataSource.cs index fd7106040de3..9b1280556831 100644 --- a/sdk/openai/Azure.AI.OpenAI/src/Custom/Chat/OnYourData/PineconeChatDataSource.cs +++ b/sdk/openai/Azure.AI.OpenAI/src/Custom/Chat/OnYourData/PineconeChatDataSource.cs @@ -1,6 +1,8 @@ // Copyright (c) Microsoft Corporation. All rights reserved. // Licensed under the MIT License. +using System; +using System.Collections.Generic; using System.Diagnostics.CodeAnalysis; namespace Azure.AI.OpenAI.Chat; @@ -15,84 +17,77 @@ public partial class PineconeChatDataSource : AzureChatDataSource required public string Environment { get => InternalParameters.Environment; - init => InternalParameters.Environment = value; + set => InternalParameters.Environment = value; } /// required public string IndexName { get => InternalParameters.IndexName; - init => InternalParameters.IndexName = value; + set => InternalParameters.IndexName = value; } /// required public DataSourceAuthentication Authentication { get => InternalParameters.Authentication; - init => InternalParameters.Authentication = value; + set => InternalParameters.Authentication = value; } /// required public DataSourceVectorizer VectorizationSource { get => InternalParameters.VectorizationSource; - init => InternalParameters.VectorizationSource = value; + set => InternalParameters.VectorizationSource = value; } /// required public DataSourceFieldMappings FieldMappings { get => InternalParameters.FieldMappings; - init => InternalParameters.FieldMappings = value; + set => InternalParameters.FieldMappings = value; } /// public int? TopNDocuments { get => InternalParameters.TopNDocuments; - init => InternalParameters.TopNDocuments = value; + set => InternalParameters.TopNDocuments = value; } /// public bool? InScope { get => InternalParameters.InScope; - init => InternalParameters.InScope = value; + set => InternalParameters.InScope = value; } /// public int? Strictness { get => InternalParameters.Strictness; - init => InternalParameters.Strictness = value; - } - - /// - public string RoleInformation - { - get => InternalParameters.RoleInformation; - init => InternalParameters.RoleInformation = value; + set => InternalParameters.Strictness = value; } /// public int? MaxSearchQueries { get => InternalParameters.MaxSearchQueries; - init => InternalParameters.MaxSearchQueries = value; + set => InternalParameters.MaxSearchQueries = value; } /// public bool? AllowPartialResult { get => InternalParameters.AllowPartialResult; - init => InternalParameters.AllowPartialResult = value; + set => InternalParameters.AllowPartialResult = value; } /// - public DataSourceOutputContextFlags? OutputContextFlags + public DataSourceOutputContexts? OutputContextFlags { get => InternalParameters.OutputContextFlags; - init => InternalParameters.OutputContextFlags = value; + set => InternalParameters.OutputContextFlags = value; } public PineconeChatDataSource() : base(type: "pinecone", serializedAdditionalRawData: null) diff --git a/sdk/openai/Azure.AI.OpenAI/src/Custom/Common/ContentFilterBlocklistResult.cs b/sdk/openai/Azure.AI.OpenAI/src/Custom/Common/ContentFilterBlocklistResult.cs index 12a3b13e2071..0bcd8f0a54db 100644 --- a/sdk/openai/Azure.AI.OpenAI/src/Custom/Common/ContentFilterBlocklistResult.cs +++ b/sdk/openai/Azure.AI.OpenAI/src/Custom/Common/ContentFilterBlocklistResult.cs @@ -1,6 +1,8 @@ // Copyright (c) Microsoft Corporation. All rights reserved. // Licensed under the MIT License. +using System.Collections.Generic; + #nullable disable namespace Azure.AI.OpenAI; diff --git a/sdk/openai/Azure.AI.OpenAI/src/Custom/Common/ContentFilterSeverityResult.cs b/sdk/openai/Azure.AI.OpenAI/src/Custom/Common/ContentFilterSeverityResult.cs new file mode 100644 index 000000000000..9331ce4c5ddc --- /dev/null +++ b/sdk/openai/Azure.AI.OpenAI/src/Custom/Common/ContentFilterSeverityResult.cs @@ -0,0 +1,11 @@ +// Copyright (c) Microsoft Corporation. All rights reserved. +// Licensed under the MIT License. + +namespace Azure.AI.OpenAI; + +[CodeGenModel("AzureContentFilterSeverityResult")] +public partial class ContentFilterSeverityResult +{ + [CodeGenMember("Severity")] + public ContentFilterSeverity Severity { get; } +} \ No newline at end of file diff --git a/sdk/openai/Azure.AI.OpenAI/src/Custom/Common/GeneratorStubs.cs b/sdk/openai/Azure.AI.OpenAI/src/Custom/Common/GeneratorStubs.cs index 6c52e65392e0..27d8658fd101 100644 --- a/sdk/openai/Azure.AI.OpenAI/src/Custom/Common/GeneratorStubs.cs +++ b/sdk/openai/Azure.AI.OpenAI/src/Custom/Common/GeneratorStubs.cs @@ -9,11 +9,6 @@ namespace Azure.AI.OpenAI; [CodeGenModel("AzureContentFilterResultForPromptContentFilterResults")] internal partial class InternalAzureContentFilterResultForPromptContentFilterResults { } [CodeGenModel("AzureContentFilterResultForPromptContentFilterResultsError")] internal partial class InternalAzureContentFilterResultForPromptContentFilterResultsError { } [CodeGenModel("AzureContentFilterSeverityResultSeverity")] public readonly partial struct ContentFilterSeverity { } -[CodeGenModel("AzureContentFilterSeverityResult")] public partial class ContentFilterSeverityResult -{ - [CodeGenMember("Severity")] - public ContentFilterSeverity Severity { get; } -} [CodeGenModel("AzureContentFilterDetectionResult")] public partial class ContentFilterDetectionResult { } [CodeGenModel("AzureOpenAIChatErrorInnerError")] internal partial class InternalAzureOpenAIChatErrorInnerError { } [CodeGenModel("AzureOpenAIChatErrorInnerErrorCode")] internal readonly partial struct InternalAzureOpenAIChatErrorInnerErrorCode { } diff --git a/sdk/openai/Azure.AI.OpenAI/src/Custom/Common/ContentFilterResultForPrompt.Serialization.cs b/sdk/openai/Azure.AI.OpenAI/src/Custom/Common/RequestContentFilterResult.Serialization.cs similarity index 85% rename from sdk/openai/Azure.AI.OpenAI/src/Custom/Common/ContentFilterResultForPrompt.Serialization.cs rename to sdk/openai/Azure.AI.OpenAI/src/Custom/Common/RequestContentFilterResult.Serialization.cs index 2116f1867534..545ee7baf368 100644 --- a/sdk/openai/Azure.AI.OpenAI/src/Custom/Common/ContentFilterResultForPrompt.Serialization.cs +++ b/sdk/openai/Azure.AI.OpenAI/src/Custom/Common/RequestContentFilterResult.Serialization.cs @@ -6,9 +6,9 @@ namespace Azure.AI.OpenAI; -public partial class ContentFilterResultForPrompt +public partial class RequestContentFilterResult { - internal static ContentFilterResultForPrompt DeserializeContentFilterResultForPrompt(JsonElement element, ModelReaderWriterOptions options = null) + internal static RequestContentFilterResult DeserializeContentFilterResultForPrompt(JsonElement element, ModelReaderWriterOptions options = null) { options ??= ModelSerializationExtensions.WireOptions; @@ -48,6 +48,6 @@ internal static ContentFilterResultForPrompt DeserializeContentFilterResultForPr } } serializedAdditionalRawData = rawDataDictionary; - return new ContentFilterResultForPrompt(promptIndex, contentFilterResults, serializedAdditionalRawData); + return new RequestContentFilterResult(promptIndex, contentFilterResults, serializedAdditionalRawData); } } diff --git a/sdk/openai/Azure.AI.OpenAI/src/Custom/Common/ContentFilterResultForPrompt.cs b/sdk/openai/Azure.AI.OpenAI/src/Custom/Common/RequestContentFilterResult.cs similarity index 97% rename from sdk/openai/Azure.AI.OpenAI/src/Custom/Common/ContentFilterResultForPrompt.cs rename to sdk/openai/Azure.AI.OpenAI/src/Custom/Common/RequestContentFilterResult.cs index 15bc9b158b27..da92948ed674 100644 --- a/sdk/openai/Azure.AI.OpenAI/src/Custom/Common/ContentFilterResultForPrompt.cs +++ b/sdk/openai/Azure.AI.OpenAI/src/Custom/Common/RequestContentFilterResult.cs @@ -4,7 +4,7 @@ namespace Azure.AI.OpenAI; [CodeGenModel("AzureContentFilterResultForPrompt")] -public partial class ContentFilterResultForPrompt +public partial class RequestContentFilterResult { internal int? PromptIndex { get; } /// Gets the content filter results. diff --git a/sdk/openai/Azure.AI.OpenAI/src/Custom/Common/ContentFilterResultForResponse.cs b/sdk/openai/Azure.AI.OpenAI/src/Custom/Common/ResponseContentFilterResult.cs similarity index 84% rename from sdk/openai/Azure.AI.OpenAI/src/Custom/Common/ContentFilterResultForResponse.cs rename to sdk/openai/Azure.AI.OpenAI/src/Custom/Common/ResponseContentFilterResult.cs index 4b21e611ec0e..1da577e9b78a 100644 --- a/sdk/openai/Azure.AI.OpenAI/src/Custom/Common/ContentFilterResultForResponse.cs +++ b/sdk/openai/Azure.AI.OpenAI/src/Custom/Common/ResponseContentFilterResult.cs @@ -4,7 +4,7 @@ namespace Azure.AI.OpenAI; [CodeGenModel("AzureContentFilterResultForChoice")] -public partial class ContentFilterResultForResponse +public partial class ResponseContentFilterResult { internal InternalAzureContentFilterResultForPromptContentFilterResultsError Error { get; } } diff --git a/sdk/openai/Azure.AI.OpenAI/src/Custom/FineTuning/AzureFineTuningClient.Protocol.cs b/sdk/openai/Azure.AI.OpenAI/src/Custom/FineTuning/AzureFineTuningClient.Protocol.cs index 479f12cde3ee..4980edceca12 100644 --- a/sdk/openai/Azure.AI.OpenAI/src/Custom/FineTuning/AzureFineTuningClient.Protocol.cs +++ b/sdk/openai/Azure.AI.OpenAI/src/Custom/FineTuning/AzureFineTuningClient.Protocol.cs @@ -4,6 +4,8 @@ using System.ClientModel; using System.ClientModel.Primitives; using System.Diagnostics.CodeAnalysis; +using System.Text.Json; +using Azure.AI.OpenAI.Utility; namespace Azure.AI.OpenAI.FineTuning; @@ -37,40 +39,67 @@ public override async Task GetJobAsync(string fineTuningJobId, Req return ClientResult.FromResponse(response); } - public override IEnumerable GetJobs(string after, int? limit, RequestOptions options) + public override CollectionResult GetJobs(string after, int? limit, RequestOptions options) { - AzureFineTuningJobsPageEnumerator enumerator = new(Pipeline, _endpoint, after, limit, _apiVersion, options); - return PageCollectionHelpers.Create(enumerator); + return new AzureCollectionResult( + Pipeline, + options, + continuation => CreateGetJobsRequestMessage(continuation?.After ?? after, continuation?.Limit ?? limit, options), + page => TryGetLastId(page, out var nextId) ? FineTuningJobCollectionPageToken.FromOptions(limit, nextId) : null, + page => ModelReaderWriter.Read(page.GetRawResponse().Content).Data); } - public override IAsyncEnumerable GetJobsAsync(string after, int? limit, RequestOptions options) + public override AsyncCollectionResult GetJobsAsync(string after, int? limit, RequestOptions options) { - AzureFineTuningJobsPageEnumerator enumerator = new(Pipeline, _endpoint, after, limit, _apiVersion, options); - return PageCollectionHelpers.CreateAsync(enumerator); + return new AzureAsyncCollectionResult( + Pipeline, + options, + continuation => CreateGetJobsRequestMessage(continuation?.After ?? after, continuation?.Limit ?? limit, options), + page => TryGetLastId(page, out var nextId) ? FineTuningJobCollectionPageToken.FromOptions(limit, nextId) : null, + page => ModelReaderWriter.Read(page.GetRawResponse().Content).Data, + options?.CancellationToken ?? default); } - public override IEnumerable GetJobEvents(string fineTuningJobId, string after, int? limit, RequestOptions options) + public override CollectionResult GetJobEvents(string fineTuningJobId, string after, int? limit, RequestOptions options) { - AzureFineTuningJobEventsPageEnumerator enumerator = new(Pipeline, _endpoint, fineTuningJobId, after, limit, _apiVersion, options); - return PageCollectionHelpers.Create(enumerator); + return new AzureCollectionResult( + Pipeline, + options, + continuation => CreateGetFineTuningEventsRequest(fineTuningJobId, continuation?.After ?? after, continuation?.Limit ?? limit, options), + page => TryGetLastId(page, out var nextId) ? FineTuningJobEventCollectionPageToken.FromOptions(fineTuningJobId, limit, nextId) : null, + page => ModelReaderWriter.Read(page.GetRawResponse().Content).Data); } - public override IAsyncEnumerable GetJobEventsAsync(string fineTuningJobId, string after, int? limit, RequestOptions options) + public override AsyncCollectionResult GetJobEventsAsync(string fineTuningJobId, string after, int? limit, RequestOptions options) { - AzureFineTuningJobEventsPageEnumerator enumerator = new(Pipeline, _endpoint, fineTuningJobId, after, limit, _apiVersion, options); - return PageCollectionHelpers.CreateAsync(enumerator); + return new AzureAsyncCollectionResult( + Pipeline, + options, + continuation => CreateGetFineTuningEventsRequest(fineTuningJobId, continuation?.After ?? after, continuation?.Limit ?? limit, options), + page => TryGetLastId(page, out var nextId) ? FineTuningJobEventCollectionPageToken.FromOptions(fineTuningJobId, limit, nextId) : null, + page => ModelReaderWriter.Read(page.GetRawResponse().Content).Data, + options?.CancellationToken ?? default); } - public override IEnumerable GetJobCheckpoints(string fineTuningJobId, string after, int? limit, RequestOptions options) + public override CollectionResult GetJobCheckpoints(string fineTuningJobId, string after, int? limit, RequestOptions options) { - AzureFineTuningJobCheckpointsPageEnumerator enumerator = new(Pipeline, _endpoint, fineTuningJobId, after, limit, _apiVersion, options); - return PageCollectionHelpers.Create(enumerator); + return new AzureCollectionResult( + Pipeline, + options, + continuation => CreateGetFineTuningJobCheckpointsRequest(fineTuningJobId, continuation?.After ?? after, continuation?.Limit ?? limit, options), + page => TryGetLastId(page, out var nextId) ? FineTuningJobCheckpointCollectionPageToken.FromOptions(fineTuningJobId, limit, nextId) : null, + page => ModelReaderWriter.Read(page.GetRawResponse().Content).Data); } - public override IAsyncEnumerable GetJobCheckpointsAsync(string fineTuningJobId, string after, int? limit, RequestOptions options) + public override AsyncCollectionResult GetJobCheckpointsAsync(string fineTuningJobId, string after, int? limit, RequestOptions options) { - AzureFineTuningJobCheckpointsPageEnumerator enumerator = new(Pipeline, _endpoint, fineTuningJobId, after, limit, _apiVersion, options); - return PageCollectionHelpers.CreateAsync(enumerator); + return new AzureAsyncCollectionResult( + Pipeline, + options, + continuation => CreateGetFineTuningJobCheckpointsRequest(fineTuningJobId, continuation?.After ?? after, continuation?.Limit ?? limit, options), + page => TryGetLastId(page, out var nextId) ? FineTuningJobCheckpointCollectionPageToken.FromOptions(fineTuningJobId, limit, nextId) : null, + page => ModelReaderWriter.Read(page.GetRawResponse().Content).Data, + options?.CancellationToken ?? default); } public override ClientResult CancelJob(string fineTuningJobId, RequestOptions options) @@ -118,6 +147,36 @@ private PipelineMessage CreateGetJobRequestMessage(string jobId, RequestOptions .WithOptions(options) .Build(); + private PipelineMessage CreateGetJobsRequestMessage(string after, int? limit, RequestOptions options) + => new AzureOpenAIPipelineMessageBuilder(Pipeline, _endpoint, _apiVersion) + .WithMethod("GET") + .WithPath("fine_tuning", "jobs") + .WithOptionalQueryParameter("after", after) + .WithOptionalQueryParameter("limit", limit) + .WithAccept("application/json") + .WithOptions(options) + .Build(); + + private new PipelineMessage CreateGetFineTuningEventsRequest(string fineTuningJobId, string after, int? limit, RequestOptions options) + => new AzureOpenAIPipelineMessageBuilder(Pipeline, _endpoint, _apiVersion) + .WithMethod("GET") + .WithPath("fine_tuning", "jobs", fineTuningJobId, "events") + .WithOptionalQueryParameter("after", after) + .WithOptionalQueryParameter("limit", limit) + .WithAccept("application/json") + .WithOptions(options) + .Build(); + + private new PipelineMessage CreateGetFineTuningJobCheckpointsRequest(string fineTuningJobId, string after, int? limit, RequestOptions options) + => new AzureOpenAIPipelineMessageBuilder(Pipeline, _endpoint, _apiVersion) + .WithMethod("GET") + .WithPath("fine_tuning", "jobs", fineTuningJobId, "checkpoints") + .WithOptionalQueryParameter("after", after) + .WithOptionalQueryParameter("limit", limit) + .WithAccept("application/json") + .WithOptions(options) + .Build(); + private PipelineMessage CreateCancelJobRequestMessage(string jobId, RequestOptions options) => new AzureOpenAIPipelineMessageBuilder(Pipeline, _endpoint, _apiVersion) .WithMethod("POST") @@ -134,4 +193,26 @@ private PipelineMessage CreateDeleteJobRequestMessage(string jobId, RequestOptio .WithClassifier(DeleteJobClassifier) .WithOptions(options) .Build(); + + private static bool TryGetLastId(ClientResult previous, out string lastId) + { + Argument.AssertNotNull(previous, nameof(previous)); + + using JsonDocument json = JsonDocument.Parse(previous.GetRawResponse().Content); + if (!json.RootElement.GetProperty("has_more"u8).GetBoolean()) + { + lastId = null; + return false; + } + + if (json?.RootElement.TryGetProperty("data", out JsonElement dataElement) == true + && dataElement.EnumerateArray().LastOrDefault().TryGetProperty("id", out JsonElement idElement) == true) + { + lastId = idElement.GetString(); + return true; + } + + lastId = null; + return false; + } } diff --git a/sdk/openai/Azure.AI.OpenAI/src/Custom/FineTuning/Pagination/AzureFineTuningJobCheckpointsPageEnumerator.cs b/sdk/openai/Azure.AI.OpenAI/src/Custom/FineTuning/Pagination/AzureFineTuningJobCheckpointsPageEnumerator.cs deleted file mode 100644 index f002a2bf596b..000000000000 --- a/sdk/openai/Azure.AI.OpenAI/src/Custom/FineTuning/Pagination/AzureFineTuningJobCheckpointsPageEnumerator.cs +++ /dev/null @@ -1,96 +0,0 @@ -// Copyright (c) Microsoft Corporation. All rights reserved. -// Licensed under the MIT License. - -#nullable enable - -using System.ClientModel; -using System.ClientModel.Primitives; -using System.Text.Json; - -namespace Azure.AI.OpenAI.FineTuning; - -internal class AzureFineTuningJobCheckpointsPageEnumerator : FineTuningJobCheckpointsPageEnumerator -{ - private readonly ClientPipeline _pipeline; - private readonly Uri _endpoint; - private readonly string _apiVersion; - - private readonly int? _limit; - private readonly string _jobId; - private readonly RequestOptions _options; - private string? _after; - - public AzureFineTuningJobCheckpointsPageEnumerator( - ClientPipeline pipeline, - Uri endpoint, - string jobId, string after, int? limit, - string apiVersion, - RequestOptions options) - : base(pipeline, endpoint, jobId, after!, limit, options) - { - _pipeline = pipeline; - _endpoint = endpoint; - _apiVersion = apiVersion; - - _jobId = jobId; - _after = after; - _limit = limit; - _options = options; - } - - public override async Task GetNextAsync(ClientResult result) - { - PipelineResponse response = result.GetRawResponse(); - - using JsonDocument doc = JsonDocument.Parse(response?.Content); - - if (doc?.RootElement.TryGetProperty("data", out JsonElement dataElement) == true - && dataElement.EnumerateArray().LastOrDefault().TryGetProperty("id", out JsonElement idElement) == true) - { - _after = idElement.GetString(); - } - - return await GetJobCheckpointsAsync(_jobId, _after!, _limit, _options).ConfigureAwait(false); - } - - public override ClientResult GetNext(ClientResult result) - { - PipelineResponse response = result.GetRawResponse(); - - using JsonDocument doc = JsonDocument.Parse(response?.Content); - - if (doc?.RootElement.TryGetProperty("data", out JsonElement dataElement) == true - && dataElement.EnumerateArray().LastOrDefault().TryGetProperty("id", out JsonElement idElement) == true) - { - _after = idElement.GetString(); - } - - return GetJobCheckpoints(_jobId, _after!, _limit, _options); - } - - internal override async Task GetJobCheckpointsAsync(string jobId, string after, int? limit, RequestOptions options) - { - Argument.AssertNotNullOrEmpty(jobId, nameof(jobId)); - - using PipelineMessage message = CreateGetFineTuningJobCheckpointsRequest(jobId, after, limit, options); - return ClientResult.FromResponse(await _pipeline.ProcessMessageAsync(message, options).ConfigureAwait(false)); - } - - internal override ClientResult GetJobCheckpoints(string jobId, string after, int? limit, RequestOptions options) - { - Argument.AssertNotNullOrEmpty(jobId, nameof(jobId)); - - using PipelineMessage message = CreateGetFineTuningJobCheckpointsRequest(jobId, after, limit, options); - return ClientResult.FromResponse(_pipeline.ProcessMessage(message, options)); - } - - internal new PipelineMessage CreateGetFineTuningJobCheckpointsRequest(string fineTuningJobId, string after, int? limit, RequestOptions options) - => new AzureOpenAIPipelineMessageBuilder(_pipeline, _endpoint, _apiVersion) - .WithMethod("GET") - .WithPath("fine_tuning", "jobs", fineTuningJobId, "checkpoints") - .WithOptionalQueryParameter("after", after) - .WithOptionalQueryParameter("limit", limit) - .WithAccept("application/json") - .WithOptions(options) - .Build(); -} diff --git a/sdk/openai/Azure.AI.OpenAI/src/Custom/FineTuning/Pagination/AzureFineTuningJobEventsPageEnumerator.cs b/sdk/openai/Azure.AI.OpenAI/src/Custom/FineTuning/Pagination/AzureFineTuningJobEventsPageEnumerator.cs deleted file mode 100644 index a18cbe777940..000000000000 --- a/sdk/openai/Azure.AI.OpenAI/src/Custom/FineTuning/Pagination/AzureFineTuningJobEventsPageEnumerator.cs +++ /dev/null @@ -1,96 +0,0 @@ -// Copyright (c) Microsoft Corporation. All rights reserved. -// Licensed under the MIT License. - -#nullable enable - -using System.ClientModel; -using System.ClientModel.Primitives; -using System.Text.Json; - -namespace Azure.AI.OpenAI.FineTuning; - -internal class AzureFineTuningJobEventsPageEnumerator : FineTuningJobEventsPageEnumerator -{ - private readonly ClientPipeline _pipeline; - private readonly Uri _endpoint; - private readonly string _apiVersion; - - private readonly int? _limit; - private readonly string _jobId; - private readonly RequestOptions _options; - private string? _after; - - public AzureFineTuningJobEventsPageEnumerator( - ClientPipeline pipeline, - Uri endpoint, - string jobId, string? after, int? limit, - string apiVersion, - RequestOptions options) - : base(pipeline, endpoint, jobId, after!, limit, options) - { - _pipeline = pipeline; - _endpoint = endpoint; - _apiVersion = apiVersion; - - _jobId = jobId; - _after = after; - _limit = limit; - _options = options; - } - - public override async Task GetNextAsync(ClientResult result) - { - PipelineResponse response = result.GetRawResponse(); - - using JsonDocument doc = JsonDocument.Parse(response?.Content); - - if (doc?.RootElement.TryGetProperty("data", out JsonElement dataElement) == true - && dataElement.EnumerateArray().LastOrDefault().TryGetProperty("id", out JsonElement idElement) == true) - { - _after = idElement.GetString(); - } - - return await GetJobEventsAsync(_jobId, _after!, _limit, _options).ConfigureAwait(false); - } - - public override ClientResult GetNext(ClientResult result) - { - PipelineResponse response = result.GetRawResponse(); - - using JsonDocument doc = JsonDocument.Parse(response?.Content); - - if (doc?.RootElement.TryGetProperty("data", out JsonElement dataElement) == true - && dataElement.EnumerateArray().LastOrDefault().TryGetProperty("id", out JsonElement idElement) == true) - { - _after = idElement.GetString(); - } - - return GetJobEvents(_jobId, _after!, _limit, _options); - } - - internal override async Task GetJobEventsAsync(string jobId, string after, int? limit, RequestOptions options) - { - Argument.AssertNotNullOrEmpty(jobId, nameof(jobId)); - - using PipelineMessage message = CreateGetFineTuningEventsRequest(jobId, after, limit, options); - return ClientResult.FromResponse(await _pipeline.ProcessMessageAsync(message, options).ConfigureAwait(false)); - } - - internal override ClientResult GetJobEvents(string jobId, string after, int? limit, RequestOptions options) - { - Argument.AssertNotNullOrEmpty(jobId, nameof(jobId)); - - using PipelineMessage message = CreateGetFineTuningEventsRequest(jobId, after, limit, options); - return ClientResult.FromResponse(_pipeline.ProcessMessage(message, options)); - } - - internal new PipelineMessage CreateGetFineTuningEventsRequest(string fineTuningJobId, string after, int? limit, RequestOptions options) - => new AzureOpenAIPipelineMessageBuilder(_pipeline, _endpoint, _apiVersion) - .WithMethod("GET") - .WithPath("fine_tuning", "jobs", fineTuningJobId, "events") - .WithOptionalQueryParameter("after", after) - .WithOptionalQueryParameter("limit", limit) - .WithAccept("application/json") - .WithOptions(options) - .Build(); -} diff --git a/sdk/openai/Azure.AI.OpenAI/src/Custom/FineTuning/Pagination/AzureFineTuningJobsPageEnumerator.cs b/sdk/openai/Azure.AI.OpenAI/src/Custom/FineTuning/Pagination/AzureFineTuningJobsPageEnumerator.cs deleted file mode 100644 index ef8a57075c9f..000000000000 --- a/sdk/openai/Azure.AI.OpenAI/src/Custom/FineTuning/Pagination/AzureFineTuningJobsPageEnumerator.cs +++ /dev/null @@ -1,91 +0,0 @@ -// Copyright (c) Microsoft Corporation. All rights reserved. -// Licensed under the MIT License. - -#nullable enable - -using System.ClientModel; -using System.ClientModel.Primitives; -using System.Text.Json; - -namespace Azure.AI.OpenAI.FineTuning; - -internal class AzureFineTuningJobsPageEnumerator : FineTuningJobsPageEnumerator -{ - private readonly ClientPipeline _pipeline; - private readonly Uri _endpoint; - private readonly string _apiVersion; - - private readonly int? _limit; - private readonly RequestOptions _options; - private string? _after; - - public AzureFineTuningJobsPageEnumerator( - ClientPipeline pipeline, - Uri endpoint, - string? after, - int? limit, - string apiVersion, - RequestOptions options) - : base(pipeline, endpoint, after!, limit, options) - { - _pipeline = pipeline; - _endpoint = endpoint; - _apiVersion = apiVersion; - - _after = after; - _limit = limit; - _options = options; - } - - public override async Task GetNextAsync(ClientResult result) - { - PipelineResponse response = result.GetRawResponse(); - - using JsonDocument doc = JsonDocument.Parse(response?.Content); - - if (doc?.RootElement.TryGetProperty("data", out JsonElement dataElement) == true - && dataElement.EnumerateArray().LastOrDefault().TryGetProperty("id", out JsonElement idElement) == true) - { - _after = idElement.GetString(); - } - - return await GetJobsAsync(_after!, _limit, _options).ConfigureAwait(false); - } - - public override ClientResult GetNext(ClientResult result) - { - PipelineResponse response = result.GetRawResponse(); - - using JsonDocument doc = JsonDocument.Parse(response?.Content); - - if (doc?.RootElement.TryGetProperty("data", out JsonElement dataElement) == true - && dataElement.EnumerateArray().LastOrDefault().TryGetProperty("id", out JsonElement idElement) == true) - { - _after = idElement.GetString(); - } - - return GetJobs(_after!, _limit, _options); - } - - internal override async Task GetJobsAsync(string after, int? limit, RequestOptions options) - { - using PipelineMessage message = CreateGetFineTuningJobsRequest(after, limit, options); - return ClientResult.FromResponse(await _pipeline.ProcessMessageAsync(message, options).ConfigureAwait(false)); - } - - internal override ClientResult GetJobs(string after, int? limit, RequestOptions options) - { - using PipelineMessage message = CreateGetFineTuningJobsRequest(after, limit, options); - return ClientResult.FromResponse(_pipeline.ProcessMessage(message, options)); - } - - internal new PipelineMessage CreateGetFineTuningJobsRequest(string? after, int? limit, RequestOptions options) - => new AzureOpenAIPipelineMessageBuilder(_pipeline, _endpoint, _apiVersion) - .WithMethod("GET") - .WithPath("fine_tuning", "jobs") - .WithOptionalQueryParameter("after", after) - .WithOptionalQueryParameter("limit", limit) - .WithAccept("application/json") - .WithOptions(options) - .Build(); -} diff --git a/sdk/openai/Azure.AI.OpenAI/src/Custom/Images/AzureGeneratedImage.cs b/sdk/openai/Azure.AI.OpenAI/src/Custom/Images/AzureGeneratedImage.cs index d0adc6fa0db5..cb7452e7ccef 100644 --- a/sdk/openai/Azure.AI.OpenAI/src/Custom/Images/AzureGeneratedImage.cs +++ b/sdk/openai/Azure.AI.OpenAI/src/Custom/Images/AzureGeneratedImage.cs @@ -5,22 +5,22 @@ using OpenAI.Images; using System.Diagnostics.CodeAnalysis; -namespace Azure.AI.OpenAI; +namespace Azure.AI.OpenAI.Images; public static class AzureGeneratedImageExtensions { [Experimental("AOAI001")] - public static ImageContentFilterResultForPrompt GetContentFilterResultForPrompt(this GeneratedImage image) + public static RequestImageContentFilterResult GetRequestContentFilterResult(this GeneratedImage image) { - return AdditionalPropertyHelpers.GetAdditionalProperty( + return AdditionalPropertyHelpers.GetAdditionalProperty( image.SerializedAdditionalRawData, "prompt_filter_results"); } [Experimental("AOAI001")] - public static ImageContentFilterResultForResponse GetContentFilterResultForResponse(this GeneratedImage image) + public static ResponseImageContentFilterResult GetResponseContentFilterResult(this GeneratedImage image) { - return AdditionalPropertyHelpers.GetAdditionalProperty( + return AdditionalPropertyHelpers.GetAdditionalProperty( image.SerializedAdditionalRawData, "content_filter_results"); } diff --git a/sdk/openai/Azure.AI.OpenAI/src/Custom/Images/GeneratorStubs.cs b/sdk/openai/Azure.AI.OpenAI/src/Custom/Images/GeneratorStubs.cs index 181c1652fd85..c9027d508ecf 100644 --- a/sdk/openai/Azure.AI.OpenAI/src/Custom/Images/GeneratorStubs.cs +++ b/sdk/openai/Azure.AI.OpenAI/src/Custom/Images/GeneratorStubs.cs @@ -3,5 +3,5 @@ namespace Azure.AI.OpenAI; -[CodeGenModel("AzureContentFilterImagePromptResults")] public partial class ImageContentFilterResultForPrompt { } -[CodeGenModel("AzureContentFilterImageResponseResults")] public partial class ImageContentFilterResultForResponse { } +[CodeGenModel("AzureContentFilterImagePromptResults")] public partial class RequestImageContentFilterResult { } +[CodeGenModel("AzureContentFilterImageResponseResults")] public partial class ResponseImageContentFilterResult { } diff --git a/sdk/openai/Azure.AI.OpenAI/src/Custom/Internal/AzureAsyncCollectionResult.cs b/sdk/openai/Azure.AI.OpenAI/src/Custom/Internal/AzureAsyncCollectionResult.cs new file mode 100644 index 000000000000..f2dc4dbee92c --- /dev/null +++ b/sdk/openai/Azure.AI.OpenAI/src/Custom/Internal/AzureAsyncCollectionResult.cs @@ -0,0 +1,84 @@ +// Copyright (c) Microsoft Corporation. All rights reserved. +// Licensed under the MIT License. + +#nullable enable + +using System.ClientModel; +using System.ClientModel.Primitives; + +namespace Azure.AI.OpenAI.Utility; + +/// +/// Represents a collection of values returned from an asynchronous Azure cloud service operation. +/// +/// The type of items in the collection. +/// Type of the continuation token. +internal class AzureAsyncCollectionResult : AsyncCollectionResult where TContinuation : ContinuationToken +{ + private readonly ClientPipeline _pipeline; + private readonly RequestOptions _options; + private readonly Func _createRequest; + private readonly Func _getContinuationToken; + private readonly Func> _getValues; + private readonly CancellationToken _cancellation; + + /// + /// Creates a new instance. + /// + /// The client pipeline to use to send requests. + /// The request options to use. + /// The function used to create the request to get a page of results. The continuation token + /// may be set to null to get the first page. After that it will be set to a value used to get the next page of results. + /// The function used to create a continuation token from a page of results. + /// The function used to extract results from a page. + /// The cancellation token to use. + /// If any of the required arguments are null. + public AzureAsyncCollectionResult( + ClientPipeline pipeline, + RequestOptions options, + Func createRequest, + Func getContinuationToken, + Func> getValues, + CancellationToken cancellation) + { + _pipeline = pipeline ?? throw new ArgumentNullException(nameof(pipeline)); + _options = options ?? new(); + _getContinuationToken = getContinuationToken ?? throw new ArgumentNullException(nameof(_getContinuationToken)); + _createRequest = createRequest ?? throw new ArgumentNullException(nameof(_createRequest)); + _getValues = getValues ?? throw new ArgumentNullException(nameof(_getContinuationToken)); + _cancellation = cancellation; + } + + /// + public override ContinuationToken? GetContinuationToken(ClientResult page) => _getContinuationToken(page); + + /// + public override async IAsyncEnumerable GetRawPagesAsync() + { + TContinuation? continuation = null; + do + { + ClientResult page = await SendRequestAsync(continuation).ConfigureAwait(false); + continuation = _getContinuationToken(page); + + yield return page; + } while (continuation != null); + } + + /// + protected override IAsyncEnumerable GetValuesFromPageAsync(ClientResult page) + => _getValues(page).ToAsyncEnumerable(_cancellation); + + /// + /// Sends a request to get the first page of results ( is null), + /// or the next page of results ( has a non-null value). + /// + /// The continuation token to use. Will be null when retrieving the first page of results. + /// The result containing the page of results. + protected virtual async Task SendRequestAsync(TContinuation? continuationToken) + { + using PipelineMessage message = _createRequest(continuationToken); + PipelineResponse response = await _pipeline.ProcessMessageAsync(message, _options).ConfigureAwait(false); + return ClientResult.FromResponse(response); + } +} diff --git a/sdk/openai/Azure.AI.OpenAI/src/Custom/Internal/AzureCollectionResult.cs b/sdk/openai/Azure.AI.OpenAI/src/Custom/Internal/AzureCollectionResult.cs new file mode 100644 index 000000000000..860ff8dd70c7 --- /dev/null +++ b/sdk/openai/Azure.AI.OpenAI/src/Custom/Internal/AzureCollectionResult.cs @@ -0,0 +1,80 @@ +// Copyright (c) Microsoft Corporation. All rights reserved. +// Licensed under the MIT License. + +#nullable enable + +using System.ClientModel; +using System.ClientModel.Primitives; + +namespace Azure.AI.OpenAI.Utility; + +/// +/// Represents a collection of values returned from an Azure cloud service operation. +/// +/// The type of items in the collection. +/// Type of the continuation token. +internal class AzureCollectionResult : CollectionResult where TContinuation : ContinuationToken +{ + private readonly ClientPipeline _pipeline; + private readonly RequestOptions _options; + private readonly Func _createRequest; + private readonly Func _getContinuationToken; + private readonly Func> _getValues; + + /// + /// Creates a new instance. + /// + /// The client pipeline to use to send requests. + /// The request options to use. + /// The function used to create the request to get a page of results. The continuation token + /// may be set to null to get the first page. After that it will be set to a value used to get the next page of results. + /// The function used to create a continuation token from a page of results. + /// The function used to extract results from a page. + /// If any of the required arguments are null. + public AzureCollectionResult( + ClientPipeline pipeline, + RequestOptions options, + Func createRequest, + Func getContinuationToken, + Func> getValues) + { + _pipeline = pipeline ?? throw new ArgumentNullException(nameof(pipeline)); + _options = options ?? new(); + _createRequest = createRequest ?? throw new ArgumentNullException(nameof(_createRequest)); + _getContinuationToken = getContinuationToken ?? throw new ArgumentNullException(nameof(_getContinuationToken)); + _getValues = getValues ?? throw new ArgumentNullException(nameof(_getContinuationToken)); + } + + /// + public override ContinuationToken? GetContinuationToken(ClientResult page) => _getContinuationToken(page); + + /// + public override IEnumerable GetRawPages() + { + TContinuation? continuation = null; + + do + { + ClientResult page = SendRequest(continuation); + continuation = _getContinuationToken(page); + + yield return page; + } + while (continuation != null); + } + + /// + protected override IEnumerable GetValuesFromPage(ClientResult page) => _getValues(page); + + /// + /// Sends a request to get the first page of results ( is null), + /// or the next page of results ( has a non-null value). + /// + /// The continuation token to use. Will be null when retrieving the first page of results. + /// The result containing the page of results. + protected virtual ClientResult SendRequest(TContinuation? continuationToken) + { + using PipelineMessage message = _createRequest(continuationToken); + return ClientResult.FromResponse(_pipeline.ProcessMessage(message, _options)); + } +} diff --git a/sdk/openai/Azure.AI.OpenAI/src/Custom/VectorStores/AzureVectorStoreClient.Protocol.cs b/sdk/openai/Azure.AI.OpenAI/src/Custom/VectorStores/AzureVectorStoreClient.Protocol.cs index 63040be8be53..22edbc7477c8 100644 --- a/sdk/openai/Azure.AI.OpenAI/src/Custom/VectorStores/AzureVectorStoreClient.Protocol.cs +++ b/sdk/openai/Azure.AI.OpenAI/src/Custom/VectorStores/AzureVectorStoreClient.Protocol.cs @@ -3,21 +3,31 @@ using System.ClientModel; using System.ClientModel.Primitives; +using Azure.AI.OpenAI.Utility; namespace Azure.AI.OpenAI.VectorStores; internal partial class AzureVectorStoreClient : VectorStoreClient { - public override IAsyncEnumerable GetVectorStoresAsync(int? limit, string order, string after, string before, RequestOptions options) + public override AsyncCollectionResult GetVectorStoresAsync(int? limit, string order, string after, string before, RequestOptions options) { - AzureVectorStoresPageEnumerator enumerator = new(Pipeline, _endpoint, limit, order, after, before, _apiVersion, options); - return PageCollectionHelpers.CreateAsync(enumerator); + return new AzureAsyncCollectionResult( + Pipeline, + options, + continuation => CreateGetVectorStoresRequest(limit, order, continuation?.After ?? after, before, options), + page => VectorStoreCollectionPageToken.FromResponse(page, limit, order, before), + page => ModelReaderWriter.Read(page.GetRawResponse().Content).Data, + options?.CancellationToken ?? default); } - public override IEnumerable GetVectorStores(int? limit, string order, string after, string before, RequestOptions options) + public override CollectionResult GetVectorStores(int? limit, string order, string after, string before, RequestOptions options) { - AzureVectorStoresPageEnumerator enumerator = new(Pipeline, _endpoint, limit, order, after, before, _apiVersion,options); - return PageCollectionHelpers.Create(enumerator); + return new AzureCollectionResult( + Pipeline, + options, + continuation => CreateGetVectorStoresRequest(limit, order, continuation?.After ?? after, before, options), + page => VectorStoreCollectionPageToken.FromResponse(page, limit, order, before), + page => ModelReaderWriter.Read(page.GetRawResponse().Content).Data); } public override async Task CreateVectorStoreAsync(BinaryContent content, RequestOptions options = null) @@ -82,20 +92,29 @@ public override ClientResult DeleteVectorStore(string vectorStoreId, RequestOpti return ClientResult.FromResponse(Pipeline.ProcessMessage(message, options)); } - public override IAsyncEnumerable GetFileAssociationsAsync(string vectorStoreId, int? limit, string order, string after, string before, string filter, RequestOptions options) + public override AsyncCollectionResult GetFileAssociationsAsync(string vectorStoreId, int? limit, string order, string after, string before, string filter, RequestOptions options) { Argument.AssertNotNullOrEmpty(vectorStoreId, nameof(vectorStoreId)); - AzureVectorStoreFilesPageEnumerator enumerator = new(Pipeline, _endpoint, vectorStoreId, limit, order, after, before, filter, _apiVersion, options); - return PageCollectionHelpers.CreateAsync(enumerator); + return new AzureAsyncCollectionResult( + Pipeline, + options, + continuation => CreateGetVectorStoreFilesRequest(vectorStoreId, limit, order, continuation?.After ?? after, before, filter, options), + page => VectorStoreFileCollectionPageToken.FromResponse(page, vectorStoreId, limit, order, before, filter), + page => ModelReaderWriter.Read(page.GetRawResponse().Content).Data, + options?.CancellationToken ?? default); } - public override IEnumerable GetFileAssociations(string vectorStoreId, int? limit, string order, string after, string before, string filter, RequestOptions options) + public override CollectionResult GetFileAssociations(string vectorStoreId, int? limit, string order, string after, string before, string filter, RequestOptions options) { Argument.AssertNotNullOrEmpty(vectorStoreId, nameof(vectorStoreId)); - AzureVectorStoreFilesPageEnumerator enumerator = new(Pipeline, _endpoint, vectorStoreId, limit, order, after, before, filter, _apiVersion, options); - return PageCollectionHelpers.Create(enumerator); + return new AzureCollectionResult( + Pipeline, + options, + continuation => CreateGetVectorStoreFilesRequest(vectorStoreId, limit, order, continuation?.After ?? after, before, filter, options), + page => VectorStoreFileCollectionPageToken.FromResponse(page, vectorStoreId, limit, order, before, filter), + page => ModelReaderWriter.Read(page.GetRawResponse().Content).Data); } public override async Task AddFileToVectorStoreAsync(string vectorStoreId, BinaryContent content, RequestOptions options = null) @@ -206,24 +225,43 @@ public override ClientResult CancelBatchFileJob(string vectorStoreId, string bat return ClientResult.FromResponse(Pipeline.ProcessMessage(message, options)); } - public override IAsyncEnumerable GetFileAssociationsAsync(string vectorStoreId, string batchId, int? limit, string order, string after, string before, string filter, RequestOptions options) + public override AsyncCollectionResult GetFileAssociationsAsync(string vectorStoreId, string batchId, int? limit, string order, string after, string before, string filter, RequestOptions options) { Argument.AssertNotNullOrEmpty(vectorStoreId, nameof(vectorStoreId)); Argument.AssertNotNullOrEmpty(batchId, nameof(batchId)); - AzureVectorStoreFileBatchesPageEnumerator enumerator = new(Pipeline, _endpoint, vectorStoreId, batchId, limit, order, after, before, filter, _apiVersion, options); - return PageCollectionHelpers.CreateAsync(enumerator); + return new AzureAsyncCollectionResult( + Pipeline, + options, + continuation => CreateGetFilesInVectorStoreBatchesRequest(vectorStoreId, batchId, limit, order, continuation?.After ?? after, before, filter, options), + page => VectorStoreFileBatchCollectionPageToken.FromResponse(page, vectorStoreId, batchId, limit, order, before, filter), + page => ModelReaderWriter.Read(page.GetRawResponse().Content).Data, + options?.CancellationToken ?? default); } - public override IEnumerable GetFileAssociations(string vectorStoreId, string batchId, int? limit, string order, string after, string before, string filter, RequestOptions options) + public override CollectionResult GetFileAssociations(string vectorStoreId, string batchId, int? limit, string order, string after, string before, string filter, RequestOptions options) { Argument.AssertNotNullOrEmpty(vectorStoreId, nameof(vectorStoreId)); Argument.AssertNotNullOrEmpty(batchId, nameof(batchId)); - AzureVectorStoreFileBatchesPageEnumerator enumerator = new(Pipeline, _endpoint, vectorStoreId, batchId, limit, order, after, before, filter, _apiVersion, options); - return PageCollectionHelpers.Create(enumerator); + return new AzureCollectionResult( + Pipeline, + options, + continuation => CreateGetFilesInVectorStoreBatchesRequest(vectorStoreId, batchId, limit, order, continuation?.After ?? after, before, filter, options), + page => VectorStoreFileBatchCollectionPageToken.FromResponse(page, vectorStoreId, batchId, limit, order, before, filter), + page => ModelReaderWriter.Read(page.GetRawResponse().Content).Data); } + private new PipelineMessage CreateGetVectorStoresRequest(int? limit, string order, string after, string before, RequestOptions options) + => new AzureOpenAIPipelineMessageBuilder(Pipeline, _endpoint, _apiVersion) + .WithAssistantsHeader() + .WithOptions(options) + .WithMethod("GET") + .WithAccept("application/json") + .WithCommonListParameters(limit, order, after, before) + .WithPath("vector_stores") + .Build(); + private new PipelineMessage CreateCreateVectorStoreRequest(BinaryContent content, RequestOptions options) => new AzureOpenAIPipelineMessageBuilder(Pipeline, _endpoint, _apiVersion) .WithMethod("POST") @@ -258,6 +296,17 @@ public override IEnumerable GetFileAssociations(string vectorStore .WithOptions(options) .Build(); + private new PipelineMessage CreateGetVectorStoreFilesRequest(string vectorStoreId, int? limit, string order, string after, string before, string filter, RequestOptions options) + => new AzureOpenAIPipelineMessageBuilder(Pipeline, _endpoint, _apiVersion) + .WithAssistantsHeader() + .WithOptions(options) + .WithMethod("GET") + .WithAccept("application/json") + .WithCommonListParameters(limit, order, after, before) + .WithOptionalQueryParameter("filter", filter) + .WithPath("vector_stores", vectorStoreId, "files") + .Build(); + private new PipelineMessage CreateCreateVectorStoreFileRequest(string vectorStoreId, BinaryContent content, RequestOptions options) => new AzureOpenAIPipelineMessageBuilder(Pipeline, _endpoint, _apiVersion) .WithMethod("POST") @@ -307,4 +356,15 @@ public override IEnumerable GetFileAssociations(string vectorStore .WithAccept("application/json") .WithOptions(options) .Build(); + + private new PipelineMessage CreateGetFilesInVectorStoreBatchesRequest(string vectorStoreId, string batchId, int? limit, string order, string after, string before, string filter, RequestOptions options) + => new AzureOpenAIPipelineMessageBuilder(Pipeline, _endpoint, _apiVersion) + .WithAssistantsHeader() + .WithOptions(options) + .WithMethod("GET") + .WithAccept("application/json") + .WithCommonListParameters(limit, order, after, before) + .WithOptionalQueryParameter("filter", filter) + .WithPath("vector_stores", vectorStoreId, "file_batches", batchId, "files") + .Build(); } diff --git a/sdk/openai/Azure.AI.OpenAI/src/Custom/VectorStores/Internal/Pagination/AzureVectorStoreFileBatchesPageEnumerator.cs b/sdk/openai/Azure.AI.OpenAI/src/Custom/VectorStores/Internal/Pagination/AzureVectorStoreFileBatchesPageEnumerator.cs deleted file mode 100644 index 21ee0a3fbcf3..000000000000 --- a/sdk/openai/Azure.AI.OpenAI/src/Custom/VectorStores/Internal/Pagination/AzureVectorStoreFileBatchesPageEnumerator.cs +++ /dev/null @@ -1,54 +0,0 @@ -// Copyright (c) Microsoft Corporation. All rights reserved. -// Licensed under the MIT License. - -using System.ClientModel; -using System.ClientModel.Primitives; - -namespace Azure.AI.OpenAI.VectorStores; - -internal partial class AzureVectorStoreFileBatchesPageEnumerator : VectorStoreFileBatchesPageEnumerator -{ - private readonly Uri _endpoint; - private readonly string _apiVersion; - - public AzureVectorStoreFileBatchesPageEnumerator( - ClientPipeline pipeline, - Uri endpoint, - string vectorStoreId, string batchId, int? limit, string order, string after, string before, string filter, - string apiVersion, - RequestOptions options) - : base(pipeline, endpoint, vectorStoreId, batchId, limit, order, after, before, filter, options) - { - _endpoint = endpoint; - _apiVersion = apiVersion; - } - - internal override async Task GetFileAssociationsAsync(string vectorStoreId, string batchId, int? limit, string order, string after, string before, string filter, RequestOptions options) - { - Argument.AssertNotNullOrEmpty(vectorStoreId, nameof(vectorStoreId)); - Argument.AssertNotNullOrEmpty(batchId, nameof(batchId)); - - using PipelineMessage message = CreateGetFilesInVectorStoreBatchesRequest(vectorStoreId, batchId, limit, order, after, before, filter, options); - return ClientResult.FromResponse(await Pipeline.ProcessMessageAsync(message, options).ConfigureAwait(false)); - } - - internal override ClientResult GetFileAssociations(string vectorStoreId, string batchId, int? limit, string order, string after, string before, string filter, RequestOptions options) - { - Argument.AssertNotNullOrEmpty(vectorStoreId, nameof(vectorStoreId)); - Argument.AssertNotNullOrEmpty(batchId, nameof(batchId)); - - using PipelineMessage message = CreateGetFilesInVectorStoreBatchesRequest(vectorStoreId, batchId, limit, order, after, before, filter, options); - return ClientResult.FromResponse(Pipeline.ProcessMessage(message, options)); - } - - private new PipelineMessage CreateGetFilesInVectorStoreBatchesRequest(string vectorStoreId, string batchId, int? limit, string order, string after, string before, string filter, RequestOptions options) - => new AzureOpenAIPipelineMessageBuilder(Pipeline, _endpoint, _apiVersion) - .WithAssistantsHeader() - .WithOptions(options) - .WithMethod("GET") - .WithAccept("application/json") - .WithCommonListParameters(limit, order, after, before) - .WithOptionalQueryParameter("filter", filter) - .WithPath("vector_stores", vectorStoreId, "file_batches", batchId, "files") - .Build(); -} diff --git a/sdk/openai/Azure.AI.OpenAI/src/Custom/VectorStores/Internal/Pagination/AzureVectorStoreFilesPageEnumerator.cs b/sdk/openai/Azure.AI.OpenAI/src/Custom/VectorStores/Internal/Pagination/AzureVectorStoreFilesPageEnumerator.cs deleted file mode 100644 index 4152a4869afa..000000000000 --- a/sdk/openai/Azure.AI.OpenAI/src/Custom/VectorStores/Internal/Pagination/AzureVectorStoreFilesPageEnumerator.cs +++ /dev/null @@ -1,53 +0,0 @@ -// Copyright (c) Microsoft Corporation. All rights reserved. -// Licensed under the MIT License. - -using System.ClientModel; -using System.ClientModel.Primitives; - -namespace Azure.AI.OpenAI.VectorStores; - -internal partial class AzureVectorStoreFilesPageEnumerator : VectorStoreFilesPageEnumerator -{ - private readonly Uri _endpoint; - private readonly string _apiVersion; - - public AzureVectorStoreFilesPageEnumerator( - ClientPipeline pipeline, - Uri endpoint, - string vectorStoreId, - int? limit, string order, string after, string before, string filter, - string apiVersion, - RequestOptions options) - : base(pipeline, endpoint, vectorStoreId, limit, order, after, before, filter, options) - { - _endpoint = endpoint; - _apiVersion = apiVersion; - } - - internal override async Task GetFileAssociationsAsync(string vectorStoreId, int? limit, string order, string after, string before, string filter, RequestOptions options) - { - Argument.AssertNotNullOrEmpty(vectorStoreId, nameof(vectorStoreId)); - - using PipelineMessage message = CreateGetVectorStoreFilesRequest(vectorStoreId, limit, order, after, before, filter, options); - return ClientResult.FromResponse(await Pipeline.ProcessMessageAsync(message, options).ConfigureAwait(false)); - } - - internal override ClientResult GetFileAssociations(string vectorStoreId, int? limit, string order, string after, string before, string filter, RequestOptions options) - { - Argument.AssertNotNullOrEmpty(vectorStoreId, nameof(vectorStoreId)); - - using PipelineMessage message = CreateGetVectorStoreFilesRequest(vectorStoreId, limit, order, after, before, filter, options); - return ClientResult.FromResponse(Pipeline.ProcessMessage(message, options)); - } - - private new PipelineMessage CreateGetVectorStoreFilesRequest(string vectorStoreId, int? limit, string order, string after, string before, string filter, RequestOptions options) - => new AzureOpenAIPipelineMessageBuilder(Pipeline, _endpoint, _apiVersion) - .WithAssistantsHeader() - .WithOptions(options) - .WithMethod("GET") - .WithAccept("application/json") - .WithCommonListParameters(limit, order, after, before) - .WithOptionalQueryParameter("filter", filter) - .WithPath("vector_stores", vectorStoreId, "files") - .Build(); -} diff --git a/sdk/openai/Azure.AI.OpenAI/src/Custom/VectorStores/Internal/Pagination/AzureVectorStoresPageEnumerator.cs b/sdk/openai/Azure.AI.OpenAI/src/Custom/VectorStores/Internal/Pagination/AzureVectorStoresPageEnumerator.cs deleted file mode 100644 index d8a90039f331..000000000000 --- a/sdk/openai/Azure.AI.OpenAI/src/Custom/VectorStores/Internal/Pagination/AzureVectorStoresPageEnumerator.cs +++ /dev/null @@ -1,47 +0,0 @@ -// Copyright (c) Microsoft Corporation. All rights reserved. -// Licensed under the MIT License. - -using System.ClientModel; -using System.ClientModel.Primitives; - -namespace Azure.AI.OpenAI.VectorStores; - -internal partial class AzureVectorStoresPageEnumerator : VectorStoresPageEnumerator -{ - private readonly Uri _endpoint; - private readonly string _apiVersion; - - public AzureVectorStoresPageEnumerator( - ClientPipeline pipeline, - Uri endpoint, - int? limit, string order, string after, string before, - string apiVersion, - RequestOptions options) - : base(pipeline, endpoint, limit, order, after, before, options) - { - _endpoint = endpoint; - _apiVersion = apiVersion; - } - - internal override async Task GetVectorStoresAsync(int? limit, string order, string after, string before, RequestOptions options) - { - using PipelineMessage message = CreateGetVectorStoresRequest(limit, order, after, before, options); - return ClientResult.FromResponse(await Pipeline.ProcessMessageAsync(message, options).ConfigureAwait(false)); - } - - internal override ClientResult GetVectorStores(int? limit, string order, string after, string before, RequestOptions options) - { - using PipelineMessage message = CreateGetVectorStoresRequest(limit, order, after, before, options); - return ClientResult.FromResponse(Pipeline.ProcessMessage(message, options)); - } - - private new PipelineMessage CreateGetVectorStoresRequest(int? limit, string order, string after, string before, RequestOptions options) - => new AzureOpenAIPipelineMessageBuilder(Pipeline, _endpoint, _apiVersion) - .WithAssistantsHeader() - .WithOptions(options) - .WithMethod("GET") - .WithAccept("application/json") - .WithCommonListParameters(limit, order, after, before) - .WithPath("vector_stores") - .Build(); -} diff --git a/sdk/openai/Azure.AI.OpenAI/src/Generated/AzureChatCitation.Serialization.cs b/sdk/openai/Azure.AI.OpenAI/src/Generated/AzureChatCitation.Serialization.cs index 7f9738eeaa69..98eb87184283 100644 --- a/sdk/openai/Azure.AI.OpenAI/src/Generated/AzureChatCitation.Serialization.cs +++ b/sdk/openai/Azure.AI.OpenAI/src/Generated/AzureChatCitation.Serialization.cs @@ -46,6 +46,11 @@ void IJsonModel.Write(Utf8JsonWriter writer, ModelReaderWrite writer.WritePropertyName("chunk_id"u8); writer.WriteStringValue(ChunkId); } + if (SerializedAdditionalRawData?.ContainsKey("rerank_score") != true && Optional.IsDefined(RerankScore)) + { + writer.WritePropertyName("rerank_score"u8); + writer.WriteNumberValue(RerankScore.Value); + } if (SerializedAdditionalRawData != null) { foreach (var item in SerializedAdditionalRawData) @@ -93,6 +98,7 @@ internal static AzureChatCitation DeserializeAzureChatCitation(JsonElement eleme string url = default; string filepath = default; string chunkId = default; + double? rerankScore = default; IDictionary serializedAdditionalRawData = default; Dictionary rawDataDictionary = new Dictionary(); foreach (var property in element.EnumerateObject()) @@ -122,6 +128,15 @@ internal static AzureChatCitation DeserializeAzureChatCitation(JsonElement eleme chunkId = property.Value.GetString(); continue; } + if (property.NameEquals("rerank_score"u8)) + { + if (property.Value.ValueKind == JsonValueKind.Null) + { + continue; + } + rerankScore = property.Value.GetDouble(); + continue; + } if (options.Format != "W") { rawDataDictionary ??= new Dictionary(); @@ -135,6 +150,7 @@ internal static AzureChatCitation DeserializeAzureChatCitation(JsonElement eleme url, filepath, chunkId, + rerankScore, serializedAdditionalRawData); } diff --git a/sdk/openai/Azure.AI.OpenAI/src/Generated/AzureChatCitation.cs b/sdk/openai/Azure.AI.OpenAI/src/Generated/AzureChatCitation.cs index 114bc7d3b7e3..cfaf82a70927 100644 --- a/sdk/openai/Azure.AI.OpenAI/src/Generated/AzureChatCitation.cs +++ b/sdk/openai/Azure.AI.OpenAI/src/Generated/AzureChatCitation.cs @@ -57,14 +57,16 @@ internal AzureChatCitation(string content) /// The URL of the citation. /// The file path for the citation. /// The chunk ID for the citation. + /// The rerank score for the retrieval. /// Keeps track of any properties unknown to the library. - internal AzureChatCitation(string content, string title, string url, string filepath, string chunkId, IDictionary serializedAdditionalRawData) + internal AzureChatCitation(string content, string title, string url, string filepath, string chunkId, double? rerankScore, IDictionary serializedAdditionalRawData) { Content = content; Title = title; Url = url; Filepath = filepath; ChunkId = chunkId; + RerankScore = rerankScore; SerializedAdditionalRawData = serializedAdditionalRawData; } @@ -83,5 +85,7 @@ internal AzureChatCitation() public string Filepath { get; } /// The chunk ID for the citation. public string ChunkId { get; } + /// The rerank score for the retrieval. + public double? RerankScore { get; } } } diff --git a/sdk/openai/Azure.AI.OpenAI/src/Generated/AzureChatDataSource.Serialization.cs b/sdk/openai/Azure.AI.OpenAI/src/Generated/AzureChatDataSource.Serialization.cs index 76263b02bcf7..3a53adc8fd91 100644 --- a/sdk/openai/Azure.AI.OpenAI/src/Generated/AzureChatDataSource.Serialization.cs +++ b/sdk/openai/Azure.AI.OpenAI/src/Generated/AzureChatDataSource.Serialization.cs @@ -73,9 +73,9 @@ internal static AzureChatDataSource DeserializeAzureChatDataSource(JsonElement e switch (discriminator.GetString()) { case "azure_cosmos_db": return AzureCosmosDBChatDataSource.DeserializeAzureCosmosDBChatDataSource(element, options); - case "azure_ml_index": return AzureMachineLearningIndexChatDataSource.DeserializeAzureMachineLearningIndexChatDataSource(element, options); case "azure_search": return AzureSearchChatDataSource.DeserializeAzureSearchChatDataSource(element, options); case "elasticsearch": return ElasticsearchChatDataSource.DeserializeElasticsearchChatDataSource(element, options); + case "mongo_db": return MongoDBChatDataSource.DeserializeMongoDBChatDataSource(element, options); case "pinecone": return PineconeChatDataSource.DeserializePineconeChatDataSource(element, options); } } diff --git a/sdk/openai/Azure.AI.OpenAI/src/Generated/AzureChatDataSource.cs b/sdk/openai/Azure.AI.OpenAI/src/Generated/AzureChatDataSource.cs index 01acaf5cf7c9..85287f4c541d 100644 --- a/sdk/openai/Azure.AI.OpenAI/src/Generated/AzureChatDataSource.cs +++ b/sdk/openai/Azure.AI.OpenAI/src/Generated/AzureChatDataSource.cs @@ -13,7 +13,7 @@ namespace Azure.AI.OpenAI.Chat /// response behavior. /// The use of this configuration is compatible only with Azure OpenAI. /// Please note is the base class. According to the scenario, a derived class of the base class might need to be assigned here, or this property needs to be casted to one of the possible derived classes. - /// The available derived classes include , , , and . + /// The available derived classes include , , , and . /// public abstract partial class AzureChatDataSource { diff --git a/sdk/openai/Azure.AI.OpenAI/src/Generated/AzureChatRetrievedDocument.Serialization.cs b/sdk/openai/Azure.AI.OpenAI/src/Generated/AzureChatRetrievedDocument.Serialization.cs index 963e4902b26c..d73498c191b1 100644 --- a/sdk/openai/Azure.AI.OpenAI/src/Generated/AzureChatRetrievedDocument.Serialization.cs +++ b/sdk/openai/Azure.AI.OpenAI/src/Generated/AzureChatRetrievedDocument.Serialization.cs @@ -46,6 +46,11 @@ void IJsonModel.Write(Utf8JsonWriter writer, ModelRe writer.WritePropertyName("chunk_id"u8); writer.WriteStringValue(ChunkId); } + if (SerializedAdditionalRawData?.ContainsKey("rerank_score") != true && Optional.IsDefined(RerankScore)) + { + writer.WritePropertyName("rerank_score"u8); + writer.WriteNumberValue(RerankScore.Value); + } if (SerializedAdditionalRawData?.ContainsKey("search_queries") != true) { writer.WritePropertyName("search_queries"u8); @@ -66,11 +71,6 @@ void IJsonModel.Write(Utf8JsonWriter writer, ModelRe writer.WritePropertyName("original_search_score"u8); writer.WriteNumberValue(OriginalSearchScore.Value); } - if (SerializedAdditionalRawData?.ContainsKey("rerank_score") != true && Optional.IsDefined(RerankScore)) - { - writer.WritePropertyName("rerank_score"u8); - writer.WriteNumberValue(RerankScore.Value); - } if (SerializedAdditionalRawData?.ContainsKey("filter_reason") != true && Optional.IsDefined(FilterReason)) { writer.WritePropertyName("filter_reason"u8); @@ -123,10 +123,10 @@ internal static AzureChatRetrievedDocument DeserializeAzureChatRetrievedDocument string url = default; string filepath = default; string chunkId = default; + double? rerankScore = default; IReadOnlyList searchQueries = default; int dataSourceIndex = default; double? originalSearchScore = default; - double? rerankScore = default; AzureChatRetrievedDocumentFilterReason? filterReason = default; IDictionary serializedAdditionalRawData = default; Dictionary rawDataDictionary = new Dictionary(); @@ -157,6 +157,15 @@ internal static AzureChatRetrievedDocument DeserializeAzureChatRetrievedDocument chunkId = property.Value.GetString(); continue; } + if (property.NameEquals("rerank_score"u8)) + { + if (property.Value.ValueKind == JsonValueKind.Null) + { + continue; + } + rerankScore = property.Value.GetDouble(); + continue; + } if (property.NameEquals("search_queries"u8)) { List array = new List(); @@ -181,15 +190,6 @@ internal static AzureChatRetrievedDocument DeserializeAzureChatRetrievedDocument originalSearchScore = property.Value.GetDouble(); continue; } - if (property.NameEquals("rerank_score"u8)) - { - if (property.Value.ValueKind == JsonValueKind.Null) - { - continue; - } - rerankScore = property.Value.GetDouble(); - continue; - } if (property.NameEquals("filter_reason"u8)) { if (property.Value.ValueKind == JsonValueKind.Null) @@ -212,10 +212,10 @@ internal static AzureChatRetrievedDocument DeserializeAzureChatRetrievedDocument url, filepath, chunkId, + rerankScore, searchQueries, dataSourceIndex, originalSearchScore, - rerankScore, filterReason, serializedAdditionalRawData); } diff --git a/sdk/openai/Azure.AI.OpenAI/src/Generated/AzureChatRetrievedDocument.cs b/sdk/openai/Azure.AI.OpenAI/src/Generated/AzureChatRetrievedDocument.cs index c0e4b0f9499f..c99b4487fe39 100644 --- a/sdk/openai/Azure.AI.OpenAI/src/Generated/AzureChatRetrievedDocument.cs +++ b/sdk/openai/Azure.AI.OpenAI/src/Generated/AzureChatRetrievedDocument.cs @@ -63,23 +63,23 @@ internal AzureChatRetrievedDocument(string content, IEnumerable searchQu /// The URL of the citation. /// The file path for the citation. /// The chunk ID for the citation. + /// The rerank score for the retrieval. /// The search queries executed to retrieve documents. /// The index of the data source used for retrieval. /// The original search score for the retrieval. - /// The rerank score for the retrieval. /// If applicable, an indication of why the document was filtered. /// Keeps track of any properties unknown to the library. - internal AzureChatRetrievedDocument(string content, string title, string url, string filepath, string chunkId, IReadOnlyList searchQueries, int dataSourceIndex, double? originalSearchScore, double? rerankScore, AzureChatRetrievedDocumentFilterReason? filterReason, IDictionary serializedAdditionalRawData) + internal AzureChatRetrievedDocument(string content, string title, string url, string filepath, string chunkId, double? rerankScore, IReadOnlyList searchQueries, int dataSourceIndex, double? originalSearchScore, AzureChatRetrievedDocumentFilterReason? filterReason, IDictionary serializedAdditionalRawData) { Content = content; Title = title; Url = url; Filepath = filepath; ChunkId = chunkId; + RerankScore = rerankScore; SearchQueries = searchQueries; DataSourceIndex = dataSourceIndex; OriginalSearchScore = originalSearchScore; - RerankScore = rerankScore; FilterReason = filterReason; SerializedAdditionalRawData = serializedAdditionalRawData; } @@ -99,14 +99,14 @@ internal AzureChatRetrievedDocument() public string Filepath { get; } /// The chunk ID for the citation. public string ChunkId { get; } + /// The rerank score for the retrieval. + public double? RerankScore { get; } /// The search queries executed to retrieve documents. public IReadOnlyList SearchQueries { get; } /// The index of the data source used for retrieval. public int DataSourceIndex { get; } /// The original search score for the retrieval. public double? OriginalSearchScore { get; } - /// The rerank score for the retrieval. - public double? RerankScore { get; } /// If applicable, an indication of why the document was filtered. public AzureChatRetrievedDocumentFilterReason? FilterReason { get; } } diff --git a/sdk/openai/Azure.AI.OpenAI/src/Generated/AzureMachineLearningIndexChatDataSource.cs b/sdk/openai/Azure.AI.OpenAI/src/Generated/AzureMachineLearningIndexChatDataSource.cs deleted file mode 100644 index 7abef53a23bf..000000000000 --- a/sdk/openai/Azure.AI.OpenAI/src/Generated/AzureMachineLearningIndexChatDataSource.cs +++ /dev/null @@ -1,14 +0,0 @@ -// - -#nullable disable - -using System; -using System.Collections.Generic; - -namespace Azure.AI.OpenAI.Chat -{ - /// Represents a data source configuration that will use an Azure Machine Learning vector index. - public partial class AzureMachineLearningIndexChatDataSource : AzureChatDataSource - { - } -} diff --git a/sdk/openai/Azure.AI.OpenAI/src/Generated/ContentFilterResultForPrompt.Serialization.cs b/sdk/openai/Azure.AI.OpenAI/src/Generated/ContentFilterResultForPrompt.Serialization.cs deleted file mode 100644 index 552f85dfa977..000000000000 --- a/sdk/openai/Azure.AI.OpenAI/src/Generated/ContentFilterResultForPrompt.Serialization.cs +++ /dev/null @@ -1,112 +0,0 @@ -// - -#nullable disable - -using System; -using System.ClientModel; -using System.ClientModel.Primitives; -using System.Text.Json; - -namespace Azure.AI.OpenAI -{ - public partial class ContentFilterResultForPrompt : IJsonModel - { - void IJsonModel.Write(Utf8JsonWriter writer, ModelReaderWriterOptions options) - { - var format = options.Format == "W" ? ((IPersistableModel)this).GetFormatFromOptions(options) : options.Format; - if (format != "J") - { - throw new FormatException($"The model {nameof(ContentFilterResultForPrompt)} does not support writing '{format}' format."); - } - - writer.WriteStartObject(); - if (SerializedAdditionalRawData?.ContainsKey("prompt_index") != true && Optional.IsDefined(PromptIndex)) - { - writer.WritePropertyName("prompt_index"u8); - writer.WriteNumberValue(PromptIndex.Value); - } - if (SerializedAdditionalRawData?.ContainsKey("content_filter_results") != true && Optional.IsDefined(InternalResults)) - { - writer.WritePropertyName("content_filter_results"u8); - writer.WriteObjectValue(InternalResults, options); - } - if (SerializedAdditionalRawData != null) - { - foreach (var item in SerializedAdditionalRawData) - { - if (ModelSerializationExtensions.IsSentinelValue(item.Value)) - { - continue; - } - writer.WritePropertyName(item.Key); -#if NET6_0_OR_GREATER - writer.WriteRawValue(item.Value); -#else - using (JsonDocument document = JsonDocument.Parse(item.Value)) - { - JsonSerializer.Serialize(writer, document.RootElement); - } -#endif - } - } - writer.WriteEndObject(); - } - - ContentFilterResultForPrompt IJsonModel.Create(ref Utf8JsonReader reader, ModelReaderWriterOptions options) - { - var format = options.Format == "W" ? ((IPersistableModel)this).GetFormatFromOptions(options) : options.Format; - if (format != "J") - { - throw new FormatException($"The model {nameof(ContentFilterResultForPrompt)} does not support reading '{format}' format."); - } - - using JsonDocument document = JsonDocument.ParseValue(ref reader); - return DeserializeContentFilterResultForPrompt(document.RootElement, options); - } - - BinaryData IPersistableModel.Write(ModelReaderWriterOptions options) - { - var format = options.Format == "W" ? ((IPersistableModel)this).GetFormatFromOptions(options) : options.Format; - - switch (format) - { - case "J": - return ModelReaderWriter.Write(this, options); - default: - throw new FormatException($"The model {nameof(ContentFilterResultForPrompt)} does not support writing '{options.Format}' format."); - } - } - - ContentFilterResultForPrompt IPersistableModel.Create(BinaryData data, ModelReaderWriterOptions options) - { - var format = options.Format == "W" ? ((IPersistableModel)this).GetFormatFromOptions(options) : options.Format; - - switch (format) - { - case "J": - { - using JsonDocument document = JsonDocument.Parse(data); - return DeserializeContentFilterResultForPrompt(document.RootElement, options); - } - default: - throw new FormatException($"The model {nameof(ContentFilterResultForPrompt)} does not support reading '{options.Format}' format."); - } - } - - string IPersistableModel.GetFormatFromOptions(ModelReaderWriterOptions options) => "J"; - - /// Deserializes the model from a raw response. - /// The result to deserialize the model from. - internal static ContentFilterResultForPrompt FromResponse(PipelineResponse response) - { - using var document = JsonDocument.Parse(response.Content); - return DeserializeContentFilterResultForPrompt(document.RootElement); - } - - /// Convert into a . - internal virtual BinaryContent ToBinaryContent() - { - return BinaryContent.Create(this, ModelSerializationExtensions.WireOptions); - } - } -} diff --git a/sdk/openai/Azure.AI.OpenAI/src/Generated/DataSourceAuthentication.Serialization.cs b/sdk/openai/Azure.AI.OpenAI/src/Generated/DataSourceAuthentication.Serialization.cs index 88ed804d9478..da7309b6f794 100644 --- a/sdk/openai/Azure.AI.OpenAI/src/Generated/DataSourceAuthentication.Serialization.cs +++ b/sdk/openai/Azure.AI.OpenAI/src/Generated/DataSourceAuthentication.Serialization.cs @@ -79,6 +79,7 @@ internal static DataSourceAuthentication DeserializeDataSourceAuthentication(Jso case "key_and_key_id": return InternalAzureChatDataSourceKeyAndKeyIdAuthenticationOptions.DeserializeInternalAzureChatDataSourceKeyAndKeyIdAuthenticationOptions(element, options); case "system_assigned_managed_identity": return InternalAzureChatDataSourceSystemAssignedManagedIdentityAuthenticationOptions.DeserializeInternalAzureChatDataSourceSystemAssignedManagedIdentityAuthenticationOptions(element, options); case "user_assigned_managed_identity": return InternalAzureChatDataSourceUserAssignedManagedIdentityAuthenticationOptions.DeserializeInternalAzureChatDataSourceUserAssignedManagedIdentityAuthenticationOptions(element, options); + case "username_and_password": return InternalAzureChatDataSourceUsernameAndPasswordAuthenticationOptions.DeserializeInternalAzureChatDataSourceUsernameAndPasswordAuthenticationOptions(element, options); } } return InternalUnknownAzureChatDataSourceAuthenticationOptions.DeserializeInternalUnknownAzureChatDataSourceAuthenticationOptions(element, options); diff --git a/sdk/openai/Azure.AI.OpenAI/src/Generated/DataSourceVectorizer.Serialization.cs b/sdk/openai/Azure.AI.OpenAI/src/Generated/DataSourceVectorizer.Serialization.cs index 15db67fa01e6..c6e4b24822ee 100644 --- a/sdk/openai/Azure.AI.OpenAI/src/Generated/DataSourceVectorizer.Serialization.cs +++ b/sdk/openai/Azure.AI.OpenAI/src/Generated/DataSourceVectorizer.Serialization.cs @@ -74,6 +74,7 @@ internal static DataSourceVectorizer DeserializeDataSourceVectorizer(JsonElement { case "deployment_name": return InternalAzureChatDataSourceDeploymentNameVectorizationSource.DeserializeInternalAzureChatDataSourceDeploymentNameVectorizationSource(element, options); case "endpoint": return InternalAzureChatDataSourceEndpointVectorizationSource.DeserializeInternalAzureChatDataSourceEndpointVectorizationSource(element, options); + case "integrated": return InternalAzureChatDataSourceIntegratedVectorizationSource.DeserializeInternalAzureChatDataSourceIntegratedVectorizationSource(element, options); case "model_id": return InternalAzureChatDataSourceModelIdVectorizationSource.DeserializeInternalAzureChatDataSourceModelIdVectorizationSource(element, options); } } diff --git a/sdk/openai/Azure.AI.OpenAI/src/Generated/Internal/BinaryContentHelper.cs b/sdk/openai/Azure.AI.OpenAI/src/Generated/Internal/BinaryContentHelper.cs index e6f35c517904..94ae48ee4fd1 100644 --- a/sdk/openai/Azure.AI.OpenAI/src/Generated/Internal/BinaryContentHelper.cs +++ b/sdk/openai/Azure.AI.OpenAI/src/Generated/Internal/BinaryContentHelper.cs @@ -53,7 +53,7 @@ public static BinaryContent FromEnumerable(IEnumerable enumerable) } public static BinaryContent FromEnumerable(ReadOnlySpan span) - where T : notnull + where T : notnull { Utf8JsonBinaryContent content = new Utf8JsonBinaryContent(); content.JsonWriter.WriteStartArray(); diff --git a/sdk/openai/Azure.AI.OpenAI/src/Generated/InternalAzureChatDataSourceAccessTokenAuthenticationOptions.cs b/sdk/openai/Azure.AI.OpenAI/src/Generated/InternalAzureChatDataSourceAccessTokenAuthenticationOptions.cs index 2fbc3dc9f61e..73fc1546e469 100644 --- a/sdk/openai/Azure.AI.OpenAI/src/Generated/InternalAzureChatDataSourceAccessTokenAuthenticationOptions.cs +++ b/sdk/openai/Azure.AI.OpenAI/src/Generated/InternalAzureChatDataSourceAccessTokenAuthenticationOptions.cs @@ -13,7 +13,7 @@ internal partial class InternalAzureChatDataSourceAccessTokenAuthenticationOptio /// Initializes a new instance of . /// /// is null. - internal InternalAzureChatDataSourceAccessTokenAuthenticationOptions(string accessToken) + public InternalAzureChatDataSourceAccessTokenAuthenticationOptions(string accessToken) { Argument.AssertNotNull(accessToken, nameof(accessToken)); diff --git a/sdk/openai/Azure.AI.OpenAI/src/Generated/InternalAzureChatDataSourceApiKeyAuthenticationOptions.cs b/sdk/openai/Azure.AI.OpenAI/src/Generated/InternalAzureChatDataSourceApiKeyAuthenticationOptions.cs index 91325ee4cdf3..1d92c00c05f7 100644 --- a/sdk/openai/Azure.AI.OpenAI/src/Generated/InternalAzureChatDataSourceApiKeyAuthenticationOptions.cs +++ b/sdk/openai/Azure.AI.OpenAI/src/Generated/InternalAzureChatDataSourceApiKeyAuthenticationOptions.cs @@ -13,7 +13,7 @@ internal partial class InternalAzureChatDataSourceApiKeyAuthenticationOptions : /// Initializes a new instance of . /// /// is null. - internal InternalAzureChatDataSourceApiKeyAuthenticationOptions(string key) + public InternalAzureChatDataSourceApiKeyAuthenticationOptions(string key) { Argument.AssertNotNull(key, nameof(key)); diff --git a/sdk/openai/Azure.AI.OpenAI/src/Generated/InternalAzureChatDataSourceConnectionStringAuthenticationOptions.cs b/sdk/openai/Azure.AI.OpenAI/src/Generated/InternalAzureChatDataSourceConnectionStringAuthenticationOptions.cs index aec71571077f..86a7f544bd27 100644 --- a/sdk/openai/Azure.AI.OpenAI/src/Generated/InternalAzureChatDataSourceConnectionStringAuthenticationOptions.cs +++ b/sdk/openai/Azure.AI.OpenAI/src/Generated/InternalAzureChatDataSourceConnectionStringAuthenticationOptions.cs @@ -13,7 +13,7 @@ internal partial class InternalAzureChatDataSourceConnectionStringAuthentication /// Initializes a new instance of . /// /// is null. - internal InternalAzureChatDataSourceConnectionStringAuthenticationOptions(string connectionString) + public InternalAzureChatDataSourceConnectionStringAuthenticationOptions(string connectionString) { Argument.AssertNotNull(connectionString, nameof(connectionString)); diff --git a/sdk/openai/Azure.AI.OpenAI/src/Generated/InternalAzureChatDataSourceDeploymentNameVectorizationSource.cs b/sdk/openai/Azure.AI.OpenAI/src/Generated/InternalAzureChatDataSourceDeploymentNameVectorizationSource.cs index 35bec8189f23..e413a85711ef 100644 --- a/sdk/openai/Azure.AI.OpenAI/src/Generated/InternalAzureChatDataSourceDeploymentNameVectorizationSource.cs +++ b/sdk/openai/Azure.AI.OpenAI/src/Generated/InternalAzureChatDataSourceDeploymentNameVectorizationSource.cs @@ -20,7 +20,7 @@ internal partial class InternalAzureChatDataSourceDeploymentNameVectorizationSou /// resource as the model deployment being used for chat completions. /// /// is null. - internal InternalAzureChatDataSourceDeploymentNameVectorizationSource(string deploymentName) + public InternalAzureChatDataSourceDeploymentNameVectorizationSource(string deploymentName) { Argument.AssertNotNull(deploymentName, nameof(deploymentName)); @@ -59,7 +59,7 @@ internal InternalAzureChatDataSourceDeploymentNameVectorizationSource() /// The number of dimensions to request on embeddings. /// Only supported in 'text-embedding-3' and later models. /// - internal int? Dimensions { get; set; } + public int? Dimensions { get; set; } } } diff --git a/sdk/openai/Azure.AI.OpenAI/src/Generated/InternalAzureChatDataSourceEncodedApiKeyAuthenticationOptions.cs b/sdk/openai/Azure.AI.OpenAI/src/Generated/InternalAzureChatDataSourceEncodedApiKeyAuthenticationOptions.cs index bb4089d7c2a9..36c145320c34 100644 --- a/sdk/openai/Azure.AI.OpenAI/src/Generated/InternalAzureChatDataSourceEncodedApiKeyAuthenticationOptions.cs +++ b/sdk/openai/Azure.AI.OpenAI/src/Generated/InternalAzureChatDataSourceEncodedApiKeyAuthenticationOptions.cs @@ -13,7 +13,7 @@ internal partial class InternalAzureChatDataSourceEncodedApiKeyAuthenticationOpt /// Initializes a new instance of . /// /// is null. - internal InternalAzureChatDataSourceEncodedApiKeyAuthenticationOptions(string encodedApiKey) + public InternalAzureChatDataSourceEncodedApiKeyAuthenticationOptions(string encodedApiKey) { Argument.AssertNotNull(encodedApiKey, nameof(encodedApiKey)); diff --git a/sdk/openai/Azure.AI.OpenAI/src/Generated/InternalAzureChatDataSourceEndpointVectorizationSource.cs b/sdk/openai/Azure.AI.OpenAI/src/Generated/InternalAzureChatDataSourceEndpointVectorizationSource.cs index 374ef45d203b..38b036485065 100644 --- a/sdk/openai/Azure.AI.OpenAI/src/Generated/InternalAzureChatDataSourceEndpointVectorizationSource.cs +++ b/sdk/openai/Azure.AI.OpenAI/src/Generated/InternalAzureChatDataSourceEndpointVectorizationSource.cs @@ -23,7 +23,7 @@ internal partial class InternalAzureChatDataSourceEndpointVectorizationSource : /// Please note is the base class. According to the scenario, a derived class of the base class might need to be assigned here, or this property needs to be casted to one of the possible derived classes.. /// /// or is null. - internal InternalAzureChatDataSourceEndpointVectorizationSource(Uri endpoint, DataSourceAuthentication authentication) + public InternalAzureChatDataSourceEndpointVectorizationSource(Uri endpoint, DataSourceAuthentication authentication) { Argument.AssertNotNull(endpoint, nameof(endpoint)); Argument.AssertNotNull(authentication, nameof(authentication)); @@ -74,7 +74,7 @@ internal InternalAzureChatDataSourceEndpointVectorizationSource() /// The number of dimensions to request on embeddings. /// Only supported in 'text-embedding-3' and later models. /// - internal int? Dimensions { get; set; } + public int? Dimensions { get; set; } } } diff --git a/sdk/openai/Azure.AI.OpenAI/src/Generated/InternalAzureChatDataSourceIntegratedVectorizationSource.Serialization.cs b/sdk/openai/Azure.AI.OpenAI/src/Generated/InternalAzureChatDataSourceIntegratedVectorizationSource.Serialization.cs new file mode 100644 index 000000000000..92c61b0e631a --- /dev/null +++ b/sdk/openai/Azure.AI.OpenAI/src/Generated/InternalAzureChatDataSourceIntegratedVectorizationSource.Serialization.cs @@ -0,0 +1,137 @@ +// + +#nullable disable + +using System; +using System.ClientModel; +using System.ClientModel.Primitives; +using System.Collections.Generic; +using System.Text.Json; + +namespace Azure.AI.OpenAI.Chat +{ + internal partial class InternalAzureChatDataSourceIntegratedVectorizationSource : IJsonModel + { + void IJsonModel.Write(Utf8JsonWriter writer, ModelReaderWriterOptions options) + { + var format = options.Format == "W" ? ((IPersistableModel)this).GetFormatFromOptions(options) : options.Format; + if (format != "J") + { + throw new FormatException($"The model {nameof(InternalAzureChatDataSourceIntegratedVectorizationSource)} does not support writing '{format}' format."); + } + + writer.WriteStartObject(); + if (SerializedAdditionalRawData?.ContainsKey("type") != true) + { + writer.WritePropertyName("type"u8); + writer.WriteStringValue(Type); + } + if (SerializedAdditionalRawData != null) + { + foreach (var item in SerializedAdditionalRawData) + { + if (ModelSerializationExtensions.IsSentinelValue(item.Value)) + { + continue; + } + writer.WritePropertyName(item.Key); +#if NET6_0_OR_GREATER + writer.WriteRawValue(item.Value); +#else + using (JsonDocument document = JsonDocument.Parse(item.Value)) + { + JsonSerializer.Serialize(writer, document.RootElement); + } +#endif + } + } + writer.WriteEndObject(); + } + + InternalAzureChatDataSourceIntegratedVectorizationSource IJsonModel.Create(ref Utf8JsonReader reader, ModelReaderWriterOptions options) + { + var format = options.Format == "W" ? ((IPersistableModel)this).GetFormatFromOptions(options) : options.Format; + if (format != "J") + { + throw new FormatException($"The model {nameof(InternalAzureChatDataSourceIntegratedVectorizationSource)} does not support reading '{format}' format."); + } + + using JsonDocument document = JsonDocument.ParseValue(ref reader); + return DeserializeInternalAzureChatDataSourceIntegratedVectorizationSource(document.RootElement, options); + } + + internal static InternalAzureChatDataSourceIntegratedVectorizationSource DeserializeInternalAzureChatDataSourceIntegratedVectorizationSource(JsonElement element, ModelReaderWriterOptions options = null) + { + options ??= ModelSerializationExtensions.WireOptions; + + if (element.ValueKind == JsonValueKind.Null) + { + return null; + } + string type = default; + IDictionary serializedAdditionalRawData = default; + Dictionary rawDataDictionary = new Dictionary(); + foreach (var property in element.EnumerateObject()) + { + if (property.NameEquals("type"u8)) + { + type = property.Value.GetString(); + continue; + } + if (options.Format != "W") + { + rawDataDictionary ??= new Dictionary(); + rawDataDictionary.Add(property.Name, BinaryData.FromString(property.Value.GetRawText())); + } + } + serializedAdditionalRawData = rawDataDictionary; + return new InternalAzureChatDataSourceIntegratedVectorizationSource(type, serializedAdditionalRawData); + } + + BinaryData IPersistableModel.Write(ModelReaderWriterOptions options) + { + var format = options.Format == "W" ? ((IPersistableModel)this).GetFormatFromOptions(options) : options.Format; + + switch (format) + { + case "J": + return ModelReaderWriter.Write(this, options); + default: + throw new FormatException($"The model {nameof(InternalAzureChatDataSourceIntegratedVectorizationSource)} does not support writing '{options.Format}' format."); + } + } + + InternalAzureChatDataSourceIntegratedVectorizationSource IPersistableModel.Create(BinaryData data, ModelReaderWriterOptions options) + { + var format = options.Format == "W" ? ((IPersistableModel)this).GetFormatFromOptions(options) : options.Format; + + switch (format) + { + case "J": + { + using JsonDocument document = JsonDocument.Parse(data); + return DeserializeInternalAzureChatDataSourceIntegratedVectorizationSource(document.RootElement, options); + } + default: + throw new FormatException($"The model {nameof(InternalAzureChatDataSourceIntegratedVectorizationSource)} does not support reading '{options.Format}' format."); + } + } + + string IPersistableModel.GetFormatFromOptions(ModelReaderWriterOptions options) => "J"; + + /// Deserializes the model from a raw response. + /// The result to deserialize the model from. + internal static new InternalAzureChatDataSourceIntegratedVectorizationSource FromResponse(PipelineResponse response) + { + using var document = JsonDocument.Parse(response.Content); + return DeserializeInternalAzureChatDataSourceIntegratedVectorizationSource(document.RootElement); + } + + /// Convert into a . + internal override BinaryContent ToBinaryContent() + { + return BinaryContent.Create(this, ModelSerializationExtensions.WireOptions); + } + } +} + diff --git a/sdk/openai/Azure.AI.OpenAI/src/Generated/InternalAzureChatDataSourceIntegratedVectorizationSource.cs b/sdk/openai/Azure.AI.OpenAI/src/Generated/InternalAzureChatDataSourceIntegratedVectorizationSource.cs new file mode 100644 index 000000000000..08fa29e39635 --- /dev/null +++ b/sdk/openai/Azure.AI.OpenAI/src/Generated/InternalAzureChatDataSourceIntegratedVectorizationSource.cs @@ -0,0 +1,27 @@ +// + +#nullable disable + +using System; +using System.Collections.Generic; + +namespace Azure.AI.OpenAI.Chat +{ + /// Represents an integrated vectorization source as defined within the supporting search resource. + internal partial class InternalAzureChatDataSourceIntegratedVectorizationSource : DataSourceVectorizer + { + /// Initializes a new instance of . + public InternalAzureChatDataSourceIntegratedVectorizationSource() + { + Type = "integrated"; + } + + /// Initializes a new instance of . + /// The differentiating identifier for the concrete vectorization source. + /// Keeps track of any properties unknown to the library. + internal InternalAzureChatDataSourceIntegratedVectorizationSource(string type, IDictionary serializedAdditionalRawData) : base(type, serializedAdditionalRawData) + { + } + } +} + diff --git a/sdk/openai/Azure.AI.OpenAI/src/Generated/InternalAzureChatDataSourceKeyAndKeyIdAuthenticationOptions.cs b/sdk/openai/Azure.AI.OpenAI/src/Generated/InternalAzureChatDataSourceKeyAndKeyIdAuthenticationOptions.cs index 9f6c3b347222..528d5880483e 100644 --- a/sdk/openai/Azure.AI.OpenAI/src/Generated/InternalAzureChatDataSourceKeyAndKeyIdAuthenticationOptions.cs +++ b/sdk/openai/Azure.AI.OpenAI/src/Generated/InternalAzureChatDataSourceKeyAndKeyIdAuthenticationOptions.cs @@ -14,7 +14,7 @@ internal partial class InternalAzureChatDataSourceKeyAndKeyIdAuthenticationOptio /// /// /// or is null. - internal InternalAzureChatDataSourceKeyAndKeyIdAuthenticationOptions(string key, string keyId) + public InternalAzureChatDataSourceKeyAndKeyIdAuthenticationOptions(string key, string keyId) { Argument.AssertNotNull(key, nameof(key)); Argument.AssertNotNull(keyId, nameof(keyId)); diff --git a/sdk/openai/Azure.AI.OpenAI/src/Generated/InternalAzureChatDataSourceSystemAssignedManagedIdentityAuthenticationOptions.cs b/sdk/openai/Azure.AI.OpenAI/src/Generated/InternalAzureChatDataSourceSystemAssignedManagedIdentityAuthenticationOptions.cs index c08da9869e9e..6b64f501d4d7 100644 --- a/sdk/openai/Azure.AI.OpenAI/src/Generated/InternalAzureChatDataSourceSystemAssignedManagedIdentityAuthenticationOptions.cs +++ b/sdk/openai/Azure.AI.OpenAI/src/Generated/InternalAzureChatDataSourceSystemAssignedManagedIdentityAuthenticationOptions.cs @@ -11,7 +11,7 @@ namespace Azure.AI.OpenAI.Chat internal partial class InternalAzureChatDataSourceSystemAssignedManagedIdentityAuthenticationOptions : DataSourceAuthentication { /// Initializes a new instance of . - internal InternalAzureChatDataSourceSystemAssignedManagedIdentityAuthenticationOptions() + public InternalAzureChatDataSourceSystemAssignedManagedIdentityAuthenticationOptions() { Type = "system_assigned_managed_identity"; } diff --git a/sdk/openai/Azure.AI.OpenAI/src/Generated/InternalAzureChatDataSourceUserAssignedManagedIdentityAuthenticationOptions.cs b/sdk/openai/Azure.AI.OpenAI/src/Generated/InternalAzureChatDataSourceUserAssignedManagedIdentityAuthenticationOptions.cs index 20e6e6b2f8a0..97f938b2bd14 100644 --- a/sdk/openai/Azure.AI.OpenAI/src/Generated/InternalAzureChatDataSourceUserAssignedManagedIdentityAuthenticationOptions.cs +++ b/sdk/openai/Azure.AI.OpenAI/src/Generated/InternalAzureChatDataSourceUserAssignedManagedIdentityAuthenticationOptions.cs @@ -13,7 +13,7 @@ internal partial class InternalAzureChatDataSourceUserAssignedManagedIdentityAut /// Initializes a new instance of . /// /// is null. - internal InternalAzureChatDataSourceUserAssignedManagedIdentityAuthenticationOptions(string managedIdentityResourceId) + public InternalAzureChatDataSourceUserAssignedManagedIdentityAuthenticationOptions(string managedIdentityResourceId) { Argument.AssertNotNull(managedIdentityResourceId, nameof(managedIdentityResourceId)); diff --git a/sdk/openai/Azure.AI.OpenAI/src/Generated/InternalAzureChatDataSourceUsernameAndPasswordAuthenticationOptions.Serialization.cs b/sdk/openai/Azure.AI.OpenAI/src/Generated/InternalAzureChatDataSourceUsernameAndPasswordAuthenticationOptions.Serialization.cs new file mode 100644 index 000000000000..4fa05a6eb3b8 --- /dev/null +++ b/sdk/openai/Azure.AI.OpenAI/src/Generated/InternalAzureChatDataSourceUsernameAndPasswordAuthenticationOptions.Serialization.cs @@ -0,0 +1,159 @@ +// + +#nullable disable + +using System; +using System.ClientModel; +using System.ClientModel.Primitives; +using System.Collections.Generic; +using System.Text.Json; + +namespace Azure.AI.OpenAI.Chat +{ + internal partial class InternalAzureChatDataSourceUsernameAndPasswordAuthenticationOptions : IJsonModel + { + void IJsonModel.Write(Utf8JsonWriter writer, ModelReaderWriterOptions options) + { + var format = options.Format == "W" ? ((IPersistableModel)this).GetFormatFromOptions(options) : options.Format; + if (format != "J") + { + throw new FormatException($"The model {nameof(InternalAzureChatDataSourceUsernameAndPasswordAuthenticationOptions)} does not support writing '{format}' format."); + } + + writer.WriteStartObject(); + if (SerializedAdditionalRawData?.ContainsKey("username") != true) + { + writer.WritePropertyName("username"u8); + writer.WriteStringValue(Username); + } + if (SerializedAdditionalRawData?.ContainsKey("password") != true) + { + writer.WritePropertyName("password"u8); + writer.WriteStringValue(Password); + } + if (SerializedAdditionalRawData?.ContainsKey("type") != true) + { + writer.WritePropertyName("type"u8); + writer.WriteStringValue(Type); + } + if (SerializedAdditionalRawData != null) + { + foreach (var item in SerializedAdditionalRawData) + { + if (ModelSerializationExtensions.IsSentinelValue(item.Value)) + { + continue; + } + writer.WritePropertyName(item.Key); +#if NET6_0_OR_GREATER + writer.WriteRawValue(item.Value); +#else + using (JsonDocument document = JsonDocument.Parse(item.Value)) + { + JsonSerializer.Serialize(writer, document.RootElement); + } +#endif + } + } + writer.WriteEndObject(); + } + + InternalAzureChatDataSourceUsernameAndPasswordAuthenticationOptions IJsonModel.Create(ref Utf8JsonReader reader, ModelReaderWriterOptions options) + { + var format = options.Format == "W" ? ((IPersistableModel)this).GetFormatFromOptions(options) : options.Format; + if (format != "J") + { + throw new FormatException($"The model {nameof(InternalAzureChatDataSourceUsernameAndPasswordAuthenticationOptions)} does not support reading '{format}' format."); + } + + using JsonDocument document = JsonDocument.ParseValue(ref reader); + return DeserializeInternalAzureChatDataSourceUsernameAndPasswordAuthenticationOptions(document.RootElement, options); + } + + internal static InternalAzureChatDataSourceUsernameAndPasswordAuthenticationOptions DeserializeInternalAzureChatDataSourceUsernameAndPasswordAuthenticationOptions(JsonElement element, ModelReaderWriterOptions options = null) + { + options ??= ModelSerializationExtensions.WireOptions; + + if (element.ValueKind == JsonValueKind.Null) + { + return null; + } + string username = default; + string password = default; + string type = default; + IDictionary serializedAdditionalRawData = default; + Dictionary rawDataDictionary = new Dictionary(); + foreach (var property in element.EnumerateObject()) + { + if (property.NameEquals("username"u8)) + { + username = property.Value.GetString(); + continue; + } + if (property.NameEquals("password"u8)) + { + password = property.Value.GetString(); + continue; + } + if (property.NameEquals("type"u8)) + { + type = property.Value.GetString(); + continue; + } + if (options.Format != "W") + { + rawDataDictionary ??= new Dictionary(); + rawDataDictionary.Add(property.Name, BinaryData.FromString(property.Value.GetRawText())); + } + } + serializedAdditionalRawData = rawDataDictionary; + return new InternalAzureChatDataSourceUsernameAndPasswordAuthenticationOptions(type, serializedAdditionalRawData, username, password); + } + + BinaryData IPersistableModel.Write(ModelReaderWriterOptions options) + { + var format = options.Format == "W" ? ((IPersistableModel)this).GetFormatFromOptions(options) : options.Format; + + switch (format) + { + case "J": + return ModelReaderWriter.Write(this, options); + default: + throw new FormatException($"The model {nameof(InternalAzureChatDataSourceUsernameAndPasswordAuthenticationOptions)} does not support writing '{options.Format}' format."); + } + } + + InternalAzureChatDataSourceUsernameAndPasswordAuthenticationOptions IPersistableModel.Create(BinaryData data, ModelReaderWriterOptions options) + { + var format = options.Format == "W" ? ((IPersistableModel)this).GetFormatFromOptions(options) : options.Format; + + switch (format) + { + case "J": + { + using JsonDocument document = JsonDocument.Parse(data); + return DeserializeInternalAzureChatDataSourceUsernameAndPasswordAuthenticationOptions(document.RootElement, options); + } + default: + throw new FormatException($"The model {nameof(InternalAzureChatDataSourceUsernameAndPasswordAuthenticationOptions)} does not support reading '{options.Format}' format."); + } + } + + string IPersistableModel.GetFormatFromOptions(ModelReaderWriterOptions options) => "J"; + + /// Deserializes the model from a raw response. + /// The result to deserialize the model from. + internal static new InternalAzureChatDataSourceUsernameAndPasswordAuthenticationOptions FromResponse(PipelineResponse response) + { + using var document = JsonDocument.Parse(response.Content); + return DeserializeInternalAzureChatDataSourceUsernameAndPasswordAuthenticationOptions(document.RootElement); + } + + /// Convert into a . + internal override BinaryContent ToBinaryContent() + { + return BinaryContent.Create(this, ModelSerializationExtensions.WireOptions); + } + } +} + diff --git a/sdk/openai/Azure.AI.OpenAI/src/Generated/InternalAzureChatDataSourceUsernameAndPasswordAuthenticationOptions.cs b/sdk/openai/Azure.AI.OpenAI/src/Generated/InternalAzureChatDataSourceUsernameAndPasswordAuthenticationOptions.cs new file mode 100644 index 000000000000..c72d02a0de9b --- /dev/null +++ b/sdk/openai/Azure.AI.OpenAI/src/Generated/InternalAzureChatDataSourceUsernameAndPasswordAuthenticationOptions.cs @@ -0,0 +1,49 @@ +// + +#nullable disable + +using System; +using System.Collections.Generic; + +namespace Azure.AI.OpenAI.Chat +{ + /// The AzureChatDataSourceUsernameAndPasswordAuthenticationOptions. + internal partial class InternalAzureChatDataSourceUsernameAndPasswordAuthenticationOptions : DataSourceAuthentication + { + /// Initializes a new instance of . + /// + /// + /// or is null. + public InternalAzureChatDataSourceUsernameAndPasswordAuthenticationOptions(string username, string password) + { + Argument.AssertNotNull(username, nameof(username)); + Argument.AssertNotNull(password, nameof(password)); + + Type = "username_and_password"; + Username = username; + Password = password; + } + + /// Initializes a new instance of . + /// Discriminator. + /// Keeps track of any properties unknown to the library. + /// + /// + internal InternalAzureChatDataSourceUsernameAndPasswordAuthenticationOptions(string type, IDictionary serializedAdditionalRawData, string username, string password) : base(type, serializedAdditionalRawData) + { + Username = username; + Password = password; + } + + /// Initializes a new instance of for deserialization. + internal InternalAzureChatDataSourceUsernameAndPasswordAuthenticationOptions() + { + } + + /// Gets the username. + internal string Username { get; set; } + /// Gets the password. + internal string Password { get; set; } + } +} + diff --git a/sdk/openai/Azure.AI.OpenAI/src/Generated/InternalAzureCosmosDBChatDataSourceParameters.Serialization.cs b/sdk/openai/Azure.AI.OpenAI/src/Generated/InternalAzureCosmosDBChatDataSourceParameters.Serialization.cs index 105a22779e07..677a0355da0b 100644 --- a/sdk/openai/Azure.AI.OpenAI/src/Generated/InternalAzureCosmosDBChatDataSourceParameters.Serialization.cs +++ b/sdk/openai/Azure.AI.OpenAI/src/Generated/InternalAzureCosmosDBChatDataSourceParameters.Serialization.cs @@ -36,11 +36,6 @@ void IJsonModel.Write(Utf8JsonWri writer.WritePropertyName("strictness"u8); writer.WriteNumberValue(Strictness.Value); } - if (SerializedAdditionalRawData?.ContainsKey("role_information") != true && Optional.IsDefined(RoleInformation)) - { - writer.WritePropertyName("role_information"u8); - writer.WriteStringValue(RoleInformation); - } if (SerializedAdditionalRawData?.ContainsKey("max_search_queries") != true && Optional.IsDefined(MaxSearchQueries)) { writer.WritePropertyName("max_search_queries"u8); @@ -136,7 +131,6 @@ internal static InternalAzureCosmosDBChatDataSourceParameters DeserializeInterna int? topNDocuments = default; bool? inScope = default; int? strictness = default; - string roleInformation = default; int? maxSearchQueries = default; bool? allowPartialResult = default; IList includeContexts = default; @@ -177,11 +171,6 @@ internal static InternalAzureCosmosDBChatDataSourceParameters DeserializeInterna strictness = property.Value.GetInt32(); continue; } - if (property.NameEquals("role_information"u8)) - { - roleInformation = property.Value.GetString(); - continue; - } if (property.NameEquals("max_search_queries"u8)) { if (property.Value.ValueKind == JsonValueKind.Null) @@ -255,7 +244,6 @@ internal static InternalAzureCosmosDBChatDataSourceParameters DeserializeInterna topNDocuments, inScope, strictness, - roleInformation, maxSearchQueries, allowPartialResult, includeContexts ?? new ChangeTrackingList(), diff --git a/sdk/openai/Azure.AI.OpenAI/src/Generated/InternalAzureCosmosDBChatDataSourceParameters.cs b/sdk/openai/Azure.AI.OpenAI/src/Generated/InternalAzureCosmosDBChatDataSourceParameters.cs index 69fcfdfdfb51..90c5774584cc 100644 --- a/sdk/openai/Azure.AI.OpenAI/src/Generated/InternalAzureCosmosDBChatDataSourceParameters.cs +++ b/sdk/openai/Azure.AI.OpenAI/src/Generated/InternalAzureCosmosDBChatDataSourceParameters.cs @@ -53,7 +53,7 @@ internal partial class InternalAzureCosmosDBChatDataSourceParameters /// /// /// , , , , or is null. - internal InternalAzureCosmosDBChatDataSourceParameters(string containerName, string databaseName, DataSourceVectorizer vectorizationSource, string indexName, DataSourceAuthentication authentication, DataSourceFieldMappings fieldMappings) + public InternalAzureCosmosDBChatDataSourceParameters(string containerName, string databaseName, DataSourceVectorizer vectorizationSource, string indexName, DataSourceAuthentication authentication, DataSourceFieldMappings fieldMappings) { Argument.AssertNotNull(containerName, nameof(containerName)); Argument.AssertNotNull(databaseName, nameof(databaseName)); @@ -78,11 +78,6 @@ internal InternalAzureCosmosDBChatDataSourceParameters(string containerName, str /// The configured strictness of the search relevance filtering. /// Higher strictness will increase precision but lower recall of the answer. /// - /// - /// Additional instructions for the model to inform how it should behave and any context it should reference when - /// generating a response. You can describe the assistant's personality and tell it how to format responses. - /// This is limited to 100 tokens and counts against the overall token limit. - /// /// /// The maximum number of rewritten queries that should be sent to the search provider for a single user message. /// By default, the system will make an automatic determination. @@ -106,12 +101,11 @@ internal InternalAzureCosmosDBChatDataSourceParameters(string containerName, str /// /// /// Keeps track of any properties unknown to the library. - internal InternalAzureCosmosDBChatDataSourceParameters(int? topNDocuments, bool? inScope, int? strictness, string roleInformation, int? maxSearchQueries, bool? allowPartialResult, IList internalIncludeContexts, string containerName, string databaseName, DataSourceVectorizer vectorizationSource, string indexName, DataSourceAuthentication authentication, DataSourceFieldMappings fieldMappings, IDictionary serializedAdditionalRawData) + internal InternalAzureCosmosDBChatDataSourceParameters(int? topNDocuments, bool? inScope, int? strictness, int? maxSearchQueries, bool? allowPartialResult, IList internalIncludeContexts, string containerName, string databaseName, DataSourceVectorizer vectorizationSource, string indexName, DataSourceAuthentication authentication, DataSourceFieldMappings fieldMappings, IDictionary serializedAdditionalRawData) { TopNDocuments = topNDocuments; InScope = inScope; Strictness = strictness; - RoleInformation = roleInformation; MaxSearchQueries = maxSearchQueries; AllowPartialResult = allowPartialResult; _internalIncludeContexts = internalIncludeContexts; @@ -130,30 +124,24 @@ internal InternalAzureCosmosDBChatDataSourceParameters() } /// The configured number of documents to feature in the query. - internal int? TopNDocuments { get; set; } + public int? TopNDocuments { get; set; } /// Whether queries should be restricted to use of the indexed data. - internal bool? InScope { get; set; } + public bool? InScope { get; set; } /// /// The configured strictness of the search relevance filtering. /// Higher strictness will increase precision but lower recall of the answer. /// - internal int? Strictness { get; set; } - /// - /// Additional instructions for the model to inform how it should behave and any context it should reference when - /// generating a response. You can describe the assistant's personality and tell it how to format responses. - /// This is limited to 100 tokens and counts against the overall token limit. - /// - internal string RoleInformation { get; set; } + public int? Strictness { get; set; } /// /// The maximum number of rewritten queries that should be sent to the search provider for a single user message. /// By default, the system will make an automatic determination. /// - internal int? MaxSearchQueries { get; set; } + public int? MaxSearchQueries { get; set; } /// /// If set to true, the system will allow partial search results to be used and the request will fail if all /// partial queries fail. If not specified or specified as false, the request will fail if any search query fails. /// - internal bool? AllowPartialResult { get; set; } + public bool? AllowPartialResult { get; set; } /// Gets the container name. internal string ContainerName { get; set; } /// Gets the database name. diff --git a/sdk/openai/Azure.AI.OpenAI/src/Generated/InternalAzureMachineLearningIndexChatDataSourceParameters.cs b/sdk/openai/Azure.AI.OpenAI/src/Generated/InternalAzureMachineLearningIndexChatDataSourceParameters.cs deleted file mode 100644 index 571ad60a248b..000000000000 --- a/sdk/openai/Azure.AI.OpenAI/src/Generated/InternalAzureMachineLearningIndexChatDataSourceParameters.cs +++ /dev/null @@ -1,155 +0,0 @@ -// - -#nullable disable - -using System; -using System.Collections.Generic; - -namespace Azure.AI.OpenAI.Chat -{ - /// The AzureMachineLearningIndexChatDataSourceParameters. - internal partial class InternalAzureMachineLearningIndexChatDataSourceParameters - { - /// - /// Keeps track of any properties unknown to the library. - /// - /// To assign an object to the value of this property use . - /// - /// - /// To assign an already formatted json string to this property use . - /// - /// - /// Examples: - /// - /// - /// BinaryData.FromObjectAsJson("foo") - /// Creates a payload of "foo". - /// - /// - /// BinaryData.FromString("\"foo\"") - /// Creates a payload of "foo". - /// - /// - /// BinaryData.FromObjectAsJson(new { key = "value" }) - /// Creates a payload of { "key": "value" }. - /// - /// - /// BinaryData.FromString("{\"key\": \"value\"}") - /// Creates a payload of { "key": "value" }. - /// - /// - /// - /// - internal IDictionary SerializedAdditionalRawData { get; set; } - /// Initializes a new instance of . - /// - /// Please note is the base class. According to the scenario, a derived class of the base class might need to be assigned here, or this property needs to be casted to one of the possible derived classes.. - /// - /// The ID of the Azure Machine Learning index project to use. - /// The name of the Azure Machine Learning index to use. - /// The version of the vector index to use. - /// , , or is null. - internal InternalAzureMachineLearningIndexChatDataSourceParameters(DataSourceAuthentication authentication, string projectResourceId, string name, string version) - { - Argument.AssertNotNull(authentication, nameof(authentication)); - Argument.AssertNotNull(projectResourceId, nameof(projectResourceId)); - Argument.AssertNotNull(name, nameof(name)); - Argument.AssertNotNull(version, nameof(version)); - - _internalIncludeContexts = new ChangeTrackingList(); - Authentication = authentication; - ProjectResourceId = projectResourceId; - Name = name; - Version = version; - } - - /// Initializes a new instance of . - /// The configured number of documents to feature in the query. - /// Whether queries should be restricted to use of the indexed data. - /// - /// The configured strictness of the search relevance filtering. - /// Higher strictness will increase precision but lower recall of the answer. - /// - /// - /// Additional instructions for the model to inform how it should behave and any context it should reference when - /// generating a response. You can describe the assistant's personality and tell it how to format responses. - /// This is limited to 100 tokens and counts against the overall token limit. - /// - /// - /// The maximum number of rewritten queries that should be sent to the search provider for a single user message. - /// By default, the system will make an automatic determination. - /// - /// - /// If set to true, the system will allow partial search results to be used and the request will fail if all - /// partial queries fail. If not specified or specified as false, the request will fail if any search query fails. - /// - /// - /// The output context properties to include on the response. - /// By default, citations and intent will be requested. - /// - /// - /// Please note is the base class. According to the scenario, a derived class of the base class might need to be assigned here, or this property needs to be casted to one of the possible derived classes.. - /// - /// The ID of the Azure Machine Learning index project to use. - /// The name of the Azure Machine Learning index to use. - /// The version of the vector index to use. - /// A search filter, which is only applicable if the vector index is of the 'AzureSearch' type. - /// Keeps track of any properties unknown to the library. - internal InternalAzureMachineLearningIndexChatDataSourceParameters(int? topNDocuments, bool? inScope, int? strictness, string roleInformation, int? maxSearchQueries, bool? allowPartialResult, IList internalIncludeContexts, DataSourceAuthentication authentication, string projectResourceId, string name, string version, string filter, IDictionary serializedAdditionalRawData) - { - TopNDocuments = topNDocuments; - InScope = inScope; - Strictness = strictness; - RoleInformation = roleInformation; - MaxSearchQueries = maxSearchQueries; - AllowPartialResult = allowPartialResult; - _internalIncludeContexts = internalIncludeContexts; - Authentication = authentication; - ProjectResourceId = projectResourceId; - Name = name; - Version = version; - Filter = filter; - SerializedAdditionalRawData = serializedAdditionalRawData; - } - - /// Initializes a new instance of for deserialization. - internal InternalAzureMachineLearningIndexChatDataSourceParameters() - { - } - - /// The configured number of documents to feature in the query. - internal int? TopNDocuments { get; set; } - /// Whether queries should be restricted to use of the indexed data. - internal bool? InScope { get; set; } - /// - /// The configured strictness of the search relevance filtering. - /// Higher strictness will increase precision but lower recall of the answer. - /// - internal int? Strictness { get; set; } - /// - /// Additional instructions for the model to inform how it should behave and any context it should reference when - /// generating a response. You can describe the assistant's personality and tell it how to format responses. - /// This is limited to 100 tokens and counts against the overall token limit. - /// - internal string RoleInformation { get; set; } - /// - /// The maximum number of rewritten queries that should be sent to the search provider for a single user message. - /// By default, the system will make an automatic determination. - /// - internal int? MaxSearchQueries { get; set; } - /// - /// If set to true, the system will allow partial search results to be used and the request will fail if all - /// partial queries fail. If not specified or specified as false, the request will fail if any search query fails. - /// - internal bool? AllowPartialResult { get; set; } - /// The ID of the Azure Machine Learning index project to use. - internal string ProjectResourceId { get; set; } - /// The name of the Azure Machine Learning index to use. - internal string Name { get; set; } - /// The version of the vector index to use. - internal string Version { get; set; } - /// A search filter, which is only applicable if the vector index is of the 'AzureSearch' type. - internal string Filter { get; set; } - } -} - diff --git a/sdk/openai/Azure.AI.OpenAI/src/Generated/InternalAzureOpenAIChatErrorInnerError.Serialization.cs b/sdk/openai/Azure.AI.OpenAI/src/Generated/InternalAzureOpenAIChatErrorInnerError.Serialization.cs index 694933771074..0a58496a1938 100644 --- a/sdk/openai/Azure.AI.OpenAI/src/Generated/InternalAzureOpenAIChatErrorInnerError.Serialization.cs +++ b/sdk/openai/Azure.AI.OpenAI/src/Generated/InternalAzureOpenAIChatErrorInnerError.Serialization.cs @@ -80,7 +80,7 @@ internal static InternalAzureOpenAIChatErrorInnerError DeserializeInternalAzureO } InternalAzureOpenAIChatErrorInnerErrorCode? code = default; string revisedPrompt = default; - ContentFilterResultForPrompt contentFilterResults = default; + RequestContentFilterResult contentFilterResults = default; IDictionary serializedAdditionalRawData = default; Dictionary rawDataDictionary = new Dictionary(); foreach (var property in element.EnumerateObject()) @@ -105,7 +105,7 @@ internal static InternalAzureOpenAIChatErrorInnerError DeserializeInternalAzureO { continue; } - contentFilterResults = ContentFilterResultForPrompt.DeserializeContentFilterResultForPrompt(property.Value, options); + contentFilterResults = RequestContentFilterResult.DeserializeRequestContentFilterResult(property.Value, options); continue; } if (options.Format != "W") diff --git a/sdk/openai/Azure.AI.OpenAI/src/Generated/InternalAzureOpenAIChatErrorInnerError.cs b/sdk/openai/Azure.AI.OpenAI/src/Generated/InternalAzureOpenAIChatErrorInnerError.cs index 0912cd016492..2209ed339feb 100644 --- a/sdk/openai/Azure.AI.OpenAI/src/Generated/InternalAzureOpenAIChatErrorInnerError.cs +++ b/sdk/openai/Azure.AI.OpenAI/src/Generated/InternalAzureOpenAIChatErrorInnerError.cs @@ -51,7 +51,7 @@ internal InternalAzureOpenAIChatErrorInnerError() /// If applicable, the modified prompt used for generation. /// The content filter result details associated with the inner error. /// Keeps track of any properties unknown to the library. - internal InternalAzureOpenAIChatErrorInnerError(InternalAzureOpenAIChatErrorInnerErrorCode? code, string revisedPrompt, ContentFilterResultForPrompt contentFilterResults, IDictionary serializedAdditionalRawData) + internal InternalAzureOpenAIChatErrorInnerError(InternalAzureOpenAIChatErrorInnerErrorCode? code, string revisedPrompt, RequestContentFilterResult contentFilterResults, IDictionary serializedAdditionalRawData) { Code = code; RevisedPrompt = revisedPrompt; @@ -64,7 +64,7 @@ internal InternalAzureOpenAIChatErrorInnerError(InternalAzureOpenAIChatErrorInne /// If applicable, the modified prompt used for generation. internal string RevisedPrompt { get; set; } /// The content filter result details associated with the inner error. - internal ContentFilterResultForPrompt ContentFilterResults { get; set; } + internal RequestContentFilterResult ContentFilterResults { get; set; } } } diff --git a/sdk/openai/Azure.AI.OpenAI/src/Generated/InternalAzureOpenAIDalleErrorInnerError.Serialization.cs b/sdk/openai/Azure.AI.OpenAI/src/Generated/InternalAzureOpenAIDalleErrorInnerError.Serialization.cs index 328bdf127b74..36e2e5564ba2 100644 --- a/sdk/openai/Azure.AI.OpenAI/src/Generated/InternalAzureOpenAIDalleErrorInnerError.Serialization.cs +++ b/sdk/openai/Azure.AI.OpenAI/src/Generated/InternalAzureOpenAIDalleErrorInnerError.Serialization.cs @@ -80,7 +80,7 @@ internal static InternalAzureOpenAIDalleErrorInnerError DeserializeInternalAzure } InternalAzureOpenAIDalleErrorInnerErrorCode? code = default; string revisedPrompt = default; - ImageContentFilterResultForPrompt contentFilterResults = default; + RequestImageContentFilterResult contentFilterResults = default; IDictionary serializedAdditionalRawData = default; Dictionary rawDataDictionary = new Dictionary(); foreach (var property in element.EnumerateObject()) @@ -105,7 +105,7 @@ internal static InternalAzureOpenAIDalleErrorInnerError DeserializeInternalAzure { continue; } - contentFilterResults = ImageContentFilterResultForPrompt.DeserializeImageContentFilterResultForPrompt(property.Value, options); + contentFilterResults = RequestImageContentFilterResult.DeserializeRequestImageContentFilterResult(property.Value, options); continue; } if (options.Format != "W") diff --git a/sdk/openai/Azure.AI.OpenAI/src/Generated/InternalAzureOpenAIDalleErrorInnerError.cs b/sdk/openai/Azure.AI.OpenAI/src/Generated/InternalAzureOpenAIDalleErrorInnerError.cs index d4b590f531cf..415434fba3a0 100644 --- a/sdk/openai/Azure.AI.OpenAI/src/Generated/InternalAzureOpenAIDalleErrorInnerError.cs +++ b/sdk/openai/Azure.AI.OpenAI/src/Generated/InternalAzureOpenAIDalleErrorInnerError.cs @@ -51,7 +51,7 @@ internal InternalAzureOpenAIDalleErrorInnerError() /// If applicable, the modified prompt used for generation. /// The content filter result details associated with the inner error. /// Keeps track of any properties unknown to the library. - internal InternalAzureOpenAIDalleErrorInnerError(InternalAzureOpenAIDalleErrorInnerErrorCode? code, string revisedPrompt, ImageContentFilterResultForPrompt contentFilterResults, IDictionary serializedAdditionalRawData) + internal InternalAzureOpenAIDalleErrorInnerError(InternalAzureOpenAIDalleErrorInnerErrorCode? code, string revisedPrompt, RequestImageContentFilterResult contentFilterResults, IDictionary serializedAdditionalRawData) { Code = code; RevisedPrompt = revisedPrompt; @@ -64,7 +64,7 @@ internal InternalAzureOpenAIDalleErrorInnerError(InternalAzureOpenAIDalleErrorIn /// If applicable, the modified prompt used for generation. internal string RevisedPrompt { get; set; } /// The content filter result details associated with the inner error. - internal ImageContentFilterResultForPrompt ContentFilterResults { get; set; } + internal RequestImageContentFilterResult ContentFilterResults { get; set; } } } diff --git a/sdk/openai/Azure.AI.OpenAI/src/Generated/InternalAzureSearchChatDataSourceParameters.Serialization.cs b/sdk/openai/Azure.AI.OpenAI/src/Generated/InternalAzureSearchChatDataSourceParameters.Serialization.cs index d855a3a0c023..49694aa0a5ec 100644 --- a/sdk/openai/Azure.AI.OpenAI/src/Generated/InternalAzureSearchChatDataSourceParameters.Serialization.cs +++ b/sdk/openai/Azure.AI.OpenAI/src/Generated/InternalAzureSearchChatDataSourceParameters.Serialization.cs @@ -36,11 +36,6 @@ void IJsonModel.Write(Utf8JsonWrite writer.WritePropertyName("strictness"u8); writer.WriteNumberValue(Strictness.Value); } - if (SerializedAdditionalRawData?.ContainsKey("role_information") != true && Optional.IsDefined(RoleInformation)) - { - writer.WritePropertyName("role_information"u8); - writer.WriteStringValue(RoleInformation); - } if (SerializedAdditionalRawData?.ContainsKey("max_search_queries") != true && Optional.IsDefined(MaxSearchQueries)) { writer.WritePropertyName("max_search_queries"u8); @@ -146,7 +141,6 @@ internal static InternalAzureSearchChatDataSourceParameters DeserializeInternalA int? topNDocuments = default; bool? inScope = default; int? strictness = default; - string roleInformation = default; int? maxSearchQueries = default; bool? allowPartialResult = default; IList includeContexts = default; @@ -189,11 +183,6 @@ internal static InternalAzureSearchChatDataSourceParameters DeserializeInternalA strictness = property.Value.GetInt32(); continue; } - if (property.NameEquals("role_information"u8)) - { - roleInformation = property.Value.GetString(); - continue; - } if (property.NameEquals("max_search_queries"u8)) { if (property.Value.ValueKind == JsonValueKind.Null) @@ -289,7 +278,6 @@ internal static InternalAzureSearchChatDataSourceParameters DeserializeInternalA topNDocuments, inScope, strictness, - roleInformation, maxSearchQueries, allowPartialResult, includeContexts ?? new ChangeTrackingList(), diff --git a/sdk/openai/Azure.AI.OpenAI/src/Generated/InternalAzureSearchChatDataSourceParameters.cs b/sdk/openai/Azure.AI.OpenAI/src/Generated/InternalAzureSearchChatDataSourceParameters.cs index 470fb9c45c7e..f46714e50404 100644 --- a/sdk/openai/Azure.AI.OpenAI/src/Generated/InternalAzureSearchChatDataSourceParameters.cs +++ b/sdk/openai/Azure.AI.OpenAI/src/Generated/InternalAzureSearchChatDataSourceParameters.cs @@ -49,7 +49,7 @@ internal partial class InternalAzureSearchChatDataSourceParameters /// Please note is the base class. According to the scenario, a derived class of the base class might need to be assigned here, or this property needs to be casted to one of the possible derived classes.. /// /// , or is null. - internal InternalAzureSearchChatDataSourceParameters(Uri endpoint, string indexName, DataSourceAuthentication authentication) + public InternalAzureSearchChatDataSourceParameters(Uri endpoint, string indexName, DataSourceAuthentication authentication) { Argument.AssertNotNull(endpoint, nameof(endpoint)); Argument.AssertNotNull(indexName, nameof(indexName)); @@ -68,11 +68,6 @@ internal InternalAzureSearchChatDataSourceParameters(Uri endpoint, string indexN /// The configured strictness of the search relevance filtering. /// Higher strictness will increase precision but lower recall of the answer. /// - /// - /// Additional instructions for the model to inform how it should behave and any context it should reference when - /// generating a response. You can describe the assistant's personality and tell it how to format responses. - /// This is limited to 100 tokens and counts against the overall token limit. - /// /// /// The maximum number of rewritten queries that should be sent to the search provider for a single user message. /// By default, the system will make an automatic determination. @@ -97,16 +92,15 @@ internal InternalAzureSearchChatDataSourceParameters(Uri endpoint, string indexN /// A filter to apply to the search. /// /// The vectorization source to use with Azure Search. - /// Supported sources for Azure Search include endpoint and deployment name. + /// Supported sources for Azure Search include endpoint, deployment name, and integrated. /// Please note is the base class. According to the scenario, a derived class of the base class might need to be assigned here, or this property needs to be casted to one of the possible derived classes.. /// /// Keeps track of any properties unknown to the library. - internal InternalAzureSearchChatDataSourceParameters(int? topNDocuments, bool? inScope, int? strictness, string roleInformation, int? maxSearchQueries, bool? allowPartialResult, IList internalIncludeContexts, Uri endpoint, string indexName, DataSourceAuthentication authentication, DataSourceFieldMappings fieldMappings, DataSourceQueryType? queryType, string semanticConfiguration, string filter, DataSourceVectorizer vectorizationSource, IDictionary serializedAdditionalRawData) + internal InternalAzureSearchChatDataSourceParameters(int? topNDocuments, bool? inScope, int? strictness, int? maxSearchQueries, bool? allowPartialResult, IList internalIncludeContexts, Uri endpoint, string indexName, DataSourceAuthentication authentication, DataSourceFieldMappings fieldMappings, DataSourceQueryType? queryType, string semanticConfiguration, string filter, DataSourceVectorizer vectorizationSource, IDictionary serializedAdditionalRawData) { TopNDocuments = topNDocuments; InScope = inScope; Strictness = strictness; - RoleInformation = roleInformation; MaxSearchQueries = maxSearchQueries; AllowPartialResult = allowPartialResult; _internalIncludeContexts = internalIncludeContexts; @@ -127,38 +121,32 @@ internal InternalAzureSearchChatDataSourceParameters() } /// The configured number of documents to feature in the query. - internal int? TopNDocuments { get; set; } + public int? TopNDocuments { get; set; } /// Whether queries should be restricted to use of the indexed data. - internal bool? InScope { get; set; } + public bool? InScope { get; set; } /// /// The configured strictness of the search relevance filtering. /// Higher strictness will increase precision but lower recall of the answer. /// - internal int? Strictness { get; set; } - /// - /// Additional instructions for the model to inform how it should behave and any context it should reference when - /// generating a response. You can describe the assistant's personality and tell it how to format responses. - /// This is limited to 100 tokens and counts against the overall token limit. - /// - internal string RoleInformation { get; set; } + public int? Strictness { get; set; } /// /// The maximum number of rewritten queries that should be sent to the search provider for a single user message. /// By default, the system will make an automatic determination. /// - internal int? MaxSearchQueries { get; set; } + public int? MaxSearchQueries { get; set; } /// /// If set to true, the system will allow partial search results to be used and the request will fail if all /// partial queries fail. If not specified or specified as false, the request will fail if any search query fails. /// - internal bool? AllowPartialResult { get; set; } + public bool? AllowPartialResult { get; set; } /// The absolute endpoint path for the Azure Search resource to use. internal Uri Endpoint { get; set; } /// The name of the index to use, as specified in the Azure Search resource. internal string IndexName { get; set; } /// Additional semantic configuration for the query. - internal string SemanticConfiguration { get; set; } + public string SemanticConfiguration { get; set; } /// A filter to apply to the search. - internal string Filter { get; set; } + public string Filter { get; set; } } } diff --git a/sdk/openai/Azure.AI.OpenAI/src/Generated/InternalElasticsearchChatDataSourceParameters.Serialization.cs b/sdk/openai/Azure.AI.OpenAI/src/Generated/InternalElasticsearchChatDataSourceParameters.Serialization.cs index 488442d4b557..f526b7d19d4e 100644 --- a/sdk/openai/Azure.AI.OpenAI/src/Generated/InternalElasticsearchChatDataSourceParameters.Serialization.cs +++ b/sdk/openai/Azure.AI.OpenAI/src/Generated/InternalElasticsearchChatDataSourceParameters.Serialization.cs @@ -36,11 +36,6 @@ void IJsonModel.Write(Utf8JsonWri writer.WritePropertyName("strictness"u8); writer.WriteNumberValue(Strictness.Value); } - if (SerializedAdditionalRawData?.ContainsKey("role_information") != true && Optional.IsDefined(RoleInformation)) - { - writer.WritePropertyName("role_information"u8); - writer.WriteStringValue(RoleInformation); - } if (SerializedAdditionalRawData?.ContainsKey("max_search_queries") != true && Optional.IsDefined(MaxSearchQueries)) { writer.WritePropertyName("max_search_queries"u8); @@ -136,7 +131,6 @@ internal static InternalElasticsearchChatDataSourceParameters DeserializeInterna int? topNDocuments = default; bool? inScope = default; int? strictness = default; - string roleInformation = default; int? maxSearchQueries = default; bool? allowPartialResult = default; IList includeContexts = default; @@ -177,11 +171,6 @@ internal static InternalElasticsearchChatDataSourceParameters DeserializeInterna strictness = property.Value.GetInt32(); continue; } - if (property.NameEquals("role_information"u8)) - { - roleInformation = property.Value.GetString(); - continue; - } if (property.NameEquals("max_search_queries"u8)) { if (property.Value.ValueKind == JsonValueKind.Null) @@ -267,7 +256,6 @@ internal static InternalElasticsearchChatDataSourceParameters DeserializeInterna topNDocuments, inScope, strictness, - roleInformation, maxSearchQueries, allowPartialResult, includeContexts ?? new ChangeTrackingList(), diff --git a/sdk/openai/Azure.AI.OpenAI/src/Generated/InternalElasticsearchChatDataSourceParameters.cs b/sdk/openai/Azure.AI.OpenAI/src/Generated/InternalElasticsearchChatDataSourceParameters.cs index fdfc831ab8a1..dcd3601dd9f7 100644 --- a/sdk/openai/Azure.AI.OpenAI/src/Generated/InternalElasticsearchChatDataSourceParameters.cs +++ b/sdk/openai/Azure.AI.OpenAI/src/Generated/InternalElasticsearchChatDataSourceParameters.cs @@ -48,7 +48,7 @@ internal partial class InternalElasticsearchChatDataSourceParameters /// Please note is the base class. According to the scenario, a derived class of the base class might need to be assigned here, or this property needs to be casted to one of the possible derived classes.. /// /// , or is null. - internal InternalElasticsearchChatDataSourceParameters(Uri endpoint, string indexName, DataSourceAuthentication authentication) + public InternalElasticsearchChatDataSourceParameters(Uri endpoint, string indexName, DataSourceAuthentication authentication) { Argument.AssertNotNull(endpoint, nameof(endpoint)); Argument.AssertNotNull(indexName, nameof(indexName)); @@ -67,11 +67,6 @@ internal InternalElasticsearchChatDataSourceParameters(Uri endpoint, string inde /// The configured strictness of the search relevance filtering. /// Higher strictness will increase precision but lower recall of the answer. /// - /// - /// Additional instructions for the model to inform how it should behave and any context it should reference when - /// generating a response. You can describe the assistant's personality and tell it how to format responses. - /// This is limited to 100 tokens and counts against the overall token limit. - /// /// /// The maximum number of rewritten queries that should be sent to the search provider for a single user message. /// By default, the system will make an automatic determination. @@ -95,12 +90,11 @@ internal InternalElasticsearchChatDataSourceParameters(Uri endpoint, string inde /// Please note is the base class. According to the scenario, a derived class of the base class might need to be assigned here, or this property needs to be casted to one of the possible derived classes.. /// /// Keeps track of any properties unknown to the library. - internal InternalElasticsearchChatDataSourceParameters(int? topNDocuments, bool? inScope, int? strictness, string roleInformation, int? maxSearchQueries, bool? allowPartialResult, IList internalIncludeContexts, Uri endpoint, string indexName, DataSourceAuthentication authentication, DataSourceFieldMappings fieldMappings, DataSourceQueryType? queryType, DataSourceVectorizer vectorizationSource, IDictionary serializedAdditionalRawData) + internal InternalElasticsearchChatDataSourceParameters(int? topNDocuments, bool? inScope, int? strictness, int? maxSearchQueries, bool? allowPartialResult, IList internalIncludeContexts, Uri endpoint, string indexName, DataSourceAuthentication authentication, DataSourceFieldMappings fieldMappings, DataSourceQueryType? queryType, DataSourceVectorizer vectorizationSource, IDictionary serializedAdditionalRawData) { TopNDocuments = topNDocuments; InScope = inScope; Strictness = strictness; - RoleInformation = roleInformation; MaxSearchQueries = maxSearchQueries; AllowPartialResult = allowPartialResult; _internalIncludeContexts = internalIncludeContexts; @@ -119,30 +113,24 @@ internal InternalElasticsearchChatDataSourceParameters() } /// The configured number of documents to feature in the query. - internal int? TopNDocuments { get; set; } + public int? TopNDocuments { get; set; } /// Whether queries should be restricted to use of the indexed data. - internal bool? InScope { get; set; } + public bool? InScope { get; set; } /// /// The configured strictness of the search relevance filtering. /// Higher strictness will increase precision but lower recall of the answer. /// - internal int? Strictness { get; set; } - /// - /// Additional instructions for the model to inform how it should behave and any context it should reference when - /// generating a response. You can describe the assistant's personality and tell it how to format responses. - /// This is limited to 100 tokens and counts against the overall token limit. - /// - internal string RoleInformation { get; set; } + public int? Strictness { get; set; } /// /// The maximum number of rewritten queries that should be sent to the search provider for a single user message. /// By default, the system will make an automatic determination. /// - internal int? MaxSearchQueries { get; set; } + public int? MaxSearchQueries { get; set; } /// /// If set to true, the system will allow partial search results to be used and the request will fail if all /// partial queries fail. If not specified or specified as false, the request will fail if any search query fails. /// - internal bool? AllowPartialResult { get; set; } + public bool? AllowPartialResult { get; set; } /// Gets the endpoint. internal Uri Endpoint { get; set; } /// Gets the index name. diff --git a/sdk/openai/Azure.AI.OpenAI/src/Generated/InternalAzureMachineLearningIndexChatDataSourceParameters.Serialization.cs b/sdk/openai/Azure.AI.OpenAI/src/Generated/InternalMongoDBChatDataSourceParameters.Serialization.cs similarity index 63% rename from sdk/openai/Azure.AI.OpenAI/src/Generated/InternalAzureMachineLearningIndexChatDataSourceParameters.Serialization.cs rename to sdk/openai/Azure.AI.OpenAI/src/Generated/InternalMongoDBChatDataSourceParameters.Serialization.cs index d5071162c444..b692f22a29c8 100644 --- a/sdk/openai/Azure.AI.OpenAI/src/Generated/InternalAzureMachineLearningIndexChatDataSourceParameters.Serialization.cs +++ b/sdk/openai/Azure.AI.OpenAI/src/Generated/InternalMongoDBChatDataSourceParameters.Serialization.cs @@ -10,14 +10,14 @@ namespace Azure.AI.OpenAI.Chat { - internal partial class InternalAzureMachineLearningIndexChatDataSourceParameters : IJsonModel + internal partial class InternalMongoDBChatDataSourceParameters : IJsonModel { - void IJsonModel.Write(Utf8JsonWriter writer, ModelReaderWriterOptions options) + void IJsonModel.Write(Utf8JsonWriter writer, ModelReaderWriterOptions options) { - var format = options.Format == "W" ? ((IPersistableModel)this).GetFormatFromOptions(options) : options.Format; + var format = options.Format == "W" ? ((IPersistableModel)this).GetFormatFromOptions(options) : options.Format; if (format != "J") { - throw new FormatException($"The model {nameof(InternalAzureMachineLearningIndexChatDataSourceParameters)} does not support writing '{format}' format."); + throw new FormatException($"The model {nameof(InternalMongoDBChatDataSourceParameters)} does not support writing '{format}' format."); } writer.WriteStartObject(); @@ -36,11 +36,6 @@ void IJsonModel.Write writer.WritePropertyName("strictness"u8); writer.WriteNumberValue(Strictness.Value); } - if (SerializedAdditionalRawData?.ContainsKey("role_information") != true && Optional.IsDefined(RoleInformation)) - { - writer.WritePropertyName("role_information"u8); - writer.WriteStringValue(RoleInformation); - } if (SerializedAdditionalRawData?.ContainsKey("max_search_queries") != true && Optional.IsDefined(MaxSearchQueries)) { writer.WritePropertyName("max_search_queries"u8); @@ -61,30 +56,45 @@ void IJsonModel.Write } writer.WriteEndArray(); } - if (SerializedAdditionalRawData?.ContainsKey("authentication") != true) + if (SerializedAdditionalRawData?.ContainsKey("endpoint") != true) { - writer.WritePropertyName("authentication"u8); - writer.WriteObjectValue(Authentication, options); + writer.WritePropertyName("endpoint"u8); + writer.WriteStringValue(Endpoint); } - if (SerializedAdditionalRawData?.ContainsKey("project_resource_id") != true) + if (SerializedAdditionalRawData?.ContainsKey("database_name") != true) { - writer.WritePropertyName("project_resource_id"u8); - writer.WriteStringValue(ProjectResourceId); + writer.WritePropertyName("database_name"u8); + writer.WriteStringValue(DatabaseName); } - if (SerializedAdditionalRawData?.ContainsKey("name") != true) + if (SerializedAdditionalRawData?.ContainsKey("collection_name") != true) { - writer.WritePropertyName("name"u8); - writer.WriteStringValue(Name); + writer.WritePropertyName("collection_name"u8); + writer.WriteStringValue(CollectionName); } - if (SerializedAdditionalRawData?.ContainsKey("version") != true) + if (SerializedAdditionalRawData?.ContainsKey("app_name") != true) { - writer.WritePropertyName("version"u8); - writer.WriteStringValue(Version); + writer.WritePropertyName("app_name"u8); + writer.WriteStringValue(AppName); } - if (SerializedAdditionalRawData?.ContainsKey("filter") != true && Optional.IsDefined(Filter)) + if (SerializedAdditionalRawData?.ContainsKey("index_name") != true) { - writer.WritePropertyName("filter"u8); - writer.WriteStringValue(Filter); + writer.WritePropertyName("index_name"u8); + writer.WriteStringValue(IndexName); + } + if (SerializedAdditionalRawData?.ContainsKey("authentication") != true) + { + writer.WritePropertyName("authentication"u8); + writer.WriteObjectValue(Authentication, options); + } + if (SerializedAdditionalRawData?.ContainsKey("embedding_dependency") != true) + { + writer.WritePropertyName("embedding_dependency"u8); + writer.WriteObjectValue(EmbeddingDependency, options); + } + if (SerializedAdditionalRawData?.ContainsKey("fields_mapping") != true) + { + writer.WritePropertyName("fields_mapping"u8); + writer.WriteObjectValue(FieldMappings, options); } if (SerializedAdditionalRawData != null) { @@ -108,19 +118,19 @@ void IJsonModel.Write writer.WriteEndObject(); } - InternalAzureMachineLearningIndexChatDataSourceParameters IJsonModel.Create(ref Utf8JsonReader reader, ModelReaderWriterOptions options) + InternalMongoDBChatDataSourceParameters IJsonModel.Create(ref Utf8JsonReader reader, ModelReaderWriterOptions options) { - var format = options.Format == "W" ? ((IPersistableModel)this).GetFormatFromOptions(options) : options.Format; + var format = options.Format == "W" ? ((IPersistableModel)this).GetFormatFromOptions(options) : options.Format; if (format != "J") { - throw new FormatException($"The model {nameof(InternalAzureMachineLearningIndexChatDataSourceParameters)} does not support reading '{format}' format."); + throw new FormatException($"The model {nameof(InternalMongoDBChatDataSourceParameters)} does not support reading '{format}' format."); } using JsonDocument document = JsonDocument.ParseValue(ref reader); - return DeserializeInternalAzureMachineLearningIndexChatDataSourceParameters(document.RootElement, options); + return DeserializeInternalMongoDBChatDataSourceParameters(document.RootElement, options); } - internal static InternalAzureMachineLearningIndexChatDataSourceParameters DeserializeInternalAzureMachineLearningIndexChatDataSourceParameters(JsonElement element, ModelReaderWriterOptions options = null) + internal static InternalMongoDBChatDataSourceParameters DeserializeInternalMongoDBChatDataSourceParameters(JsonElement element, ModelReaderWriterOptions options = null) { options ??= ModelSerializationExtensions.WireOptions; @@ -131,15 +141,17 @@ internal static InternalAzureMachineLearningIndexChatDataSourceParameters Deseri int? topNDocuments = default; bool? inScope = default; int? strictness = default; - string roleInformation = default; int? maxSearchQueries = default; bool? allowPartialResult = default; IList includeContexts = default; + string endpoint = default; + string databaseName = default; + string collectionName = default; + string appName = default; + string indexName = default; DataSourceAuthentication authentication = default; - string projectResourceId = default; - string name = default; - string version = default; - string filter = default; + DataSourceVectorizer embeddingDependency = default; + DataSourceFieldMappings fieldsMapping = default; IDictionary serializedAdditionalRawData = default; Dictionary rawDataDictionary = new Dictionary(); foreach (var property in element.EnumerateObject()) @@ -171,11 +183,6 @@ internal static InternalAzureMachineLearningIndexChatDataSourceParameters Deseri strictness = property.Value.GetInt32(); continue; } - if (property.NameEquals("role_information"u8)) - { - roleInformation = property.Value.GetString(); - continue; - } if (property.NameEquals("max_search_queries"u8)) { if (property.Value.ValueKind == JsonValueKind.Null) @@ -208,29 +215,44 @@ internal static InternalAzureMachineLearningIndexChatDataSourceParameters Deseri includeContexts = array; continue; } - if (property.NameEquals("authentication"u8)) + if (property.NameEquals("endpoint"u8)) { - authentication = DataSourceAuthentication.DeserializeDataSourceAuthentication(property.Value, options); + endpoint = property.Value.GetString(); continue; } - if (property.NameEquals("project_resource_id"u8)) + if (property.NameEquals("database_name"u8)) { - projectResourceId = property.Value.GetString(); + databaseName = property.Value.GetString(); continue; } - if (property.NameEquals("name"u8)) + if (property.NameEquals("collection_name"u8)) { - name = property.Value.GetString(); + collectionName = property.Value.GetString(); + continue; + } + if (property.NameEquals("app_name"u8)) + { + appName = property.Value.GetString(); + continue; + } + if (property.NameEquals("index_name"u8)) + { + indexName = property.Value.GetString(); + continue; + } + if (property.NameEquals("authentication"u8)) + { + authentication = DataSourceAuthentication.DeserializeDataSourceAuthentication(property.Value, options); continue; } - if (property.NameEquals("version"u8)) + if (property.NameEquals("embedding_dependency"u8)) { - version = property.Value.GetString(); + embeddingDependency = DataSourceVectorizer.DeserializeDataSourceVectorizer(property.Value, options); continue; } - if (property.NameEquals("filter"u8)) + if (property.NameEquals("fields_mapping"u8)) { - filter = property.Value.GetString(); + fieldsMapping = DataSourceFieldMappings.DeserializeDataSourceFieldMappings(property.Value, options); continue; } if (options.Format != "W") @@ -240,59 +262,61 @@ internal static InternalAzureMachineLearningIndexChatDataSourceParameters Deseri } } serializedAdditionalRawData = rawDataDictionary; - return new InternalAzureMachineLearningIndexChatDataSourceParameters( + return new InternalMongoDBChatDataSourceParameters( topNDocuments, inScope, strictness, - roleInformation, maxSearchQueries, allowPartialResult, includeContexts ?? new ChangeTrackingList(), + endpoint, + databaseName, + collectionName, + appName, + indexName, authentication, - projectResourceId, - name, - version, - filter, + embeddingDependency, + fieldsMapping, serializedAdditionalRawData); } - BinaryData IPersistableModel.Write(ModelReaderWriterOptions options) + BinaryData IPersistableModel.Write(ModelReaderWriterOptions options) { - var format = options.Format == "W" ? ((IPersistableModel)this).GetFormatFromOptions(options) : options.Format; + var format = options.Format == "W" ? ((IPersistableModel)this).GetFormatFromOptions(options) : options.Format; switch (format) { case "J": return ModelReaderWriter.Write(this, options); default: - throw new FormatException($"The model {nameof(InternalAzureMachineLearningIndexChatDataSourceParameters)} does not support writing '{options.Format}' format."); + throw new FormatException($"The model {nameof(InternalMongoDBChatDataSourceParameters)} does not support writing '{options.Format}' format."); } } - InternalAzureMachineLearningIndexChatDataSourceParameters IPersistableModel.Create(BinaryData data, ModelReaderWriterOptions options) + InternalMongoDBChatDataSourceParameters IPersistableModel.Create(BinaryData data, ModelReaderWriterOptions options) { - var format = options.Format == "W" ? ((IPersistableModel)this).GetFormatFromOptions(options) : options.Format; + var format = options.Format == "W" ? ((IPersistableModel)this).GetFormatFromOptions(options) : options.Format; switch (format) { case "J": { using JsonDocument document = JsonDocument.Parse(data); - return DeserializeInternalAzureMachineLearningIndexChatDataSourceParameters(document.RootElement, options); + return DeserializeInternalMongoDBChatDataSourceParameters(document.RootElement, options); } default: - throw new FormatException($"The model {nameof(InternalAzureMachineLearningIndexChatDataSourceParameters)} does not support reading '{options.Format}' format."); + throw new FormatException($"The model {nameof(InternalMongoDBChatDataSourceParameters)} does not support reading '{options.Format}' format."); } } - string IPersistableModel.GetFormatFromOptions(ModelReaderWriterOptions options) => "J"; + string IPersistableModel.GetFormatFromOptions(ModelReaderWriterOptions options) => "J"; /// Deserializes the model from a raw response. /// The result to deserialize the model from. - internal static InternalAzureMachineLearningIndexChatDataSourceParameters FromResponse(PipelineResponse response) + internal static InternalMongoDBChatDataSourceParameters FromResponse(PipelineResponse response) { using var document = JsonDocument.Parse(response.Content); - return DeserializeInternalAzureMachineLearningIndexChatDataSourceParameters(document.RootElement); + return DeserializeInternalMongoDBChatDataSourceParameters(document.RootElement); } /// Convert into a . diff --git a/sdk/openai/Azure.AI.OpenAI/src/Generated/InternalMongoDBChatDataSourceParameters.cs b/sdk/openai/Azure.AI.OpenAI/src/Generated/InternalMongoDBChatDataSourceParameters.cs new file mode 100644 index 000000000000..52ccc319dc6f --- /dev/null +++ b/sdk/openai/Azure.AI.OpenAI/src/Generated/InternalMongoDBChatDataSourceParameters.cs @@ -0,0 +1,181 @@ +// + +#nullable disable + +using System; +using System.Collections.Generic; + +namespace Azure.AI.OpenAI.Chat +{ + /// The MongoDBChatDataSourceParameters. + internal partial class InternalMongoDBChatDataSourceParameters + { + /// + /// Keeps track of any properties unknown to the library. + /// + /// To assign an object to the value of this property use . + /// + /// + /// To assign an already formatted json string to this property use . + /// + /// + /// Examples: + /// + /// + /// BinaryData.FromObjectAsJson("foo") + /// Creates a payload of "foo". + /// + /// + /// BinaryData.FromString("\"foo\"") + /// Creates a payload of "foo". + /// + /// + /// BinaryData.FromObjectAsJson(new { key = "value" }) + /// Creates a payload of { "key": "value" }. + /// + /// + /// BinaryData.FromString("{\"key\": \"value\"}") + /// Creates a payload of { "key": "value" }. + /// + /// + /// + /// + internal IDictionary SerializedAdditionalRawData { get; set; } + /// Initializes a new instance of . + /// The name of the MongoDB cluster endpoint. + /// The name of the MongoDB database. + /// The name of the MongoDB collection. + /// The name of the MongoDB application. + /// The name of the MongoDB index. + /// + /// The authentication mechanism to use with Pinecone. + /// Supported authentication mechanisms for Pinecone include: username and password. + /// Please note is the base class. According to the scenario, a derived class of the base class might need to be assigned here, or this property needs to be casted to one of the possible derived classes.. + /// + /// + /// The vectorization source to use as an embedding dependency for the MongoDB data source. + /// Supported vectorization sources for MongoDB include: endpoint, deployment name. + /// Please note is the base class. According to the scenario, a derived class of the base class might need to be assigned here, or this property needs to be casted to one of the possible derived classes.. + /// + /// + /// Field mappings to apply to data used by the MongoDB data source. + /// Note that content and vector field mappings are required for MongoDB. + /// + /// , , , , , , or is null. + public InternalMongoDBChatDataSourceParameters(string endpoint, string databaseName, string collectionName, string appName, string indexName, DataSourceAuthentication authentication, DataSourceVectorizer embeddingDependency, DataSourceFieldMappings fieldMappings) + { + Argument.AssertNotNull(endpoint, nameof(endpoint)); + Argument.AssertNotNull(databaseName, nameof(databaseName)); + Argument.AssertNotNull(collectionName, nameof(collectionName)); + Argument.AssertNotNull(appName, nameof(appName)); + Argument.AssertNotNull(indexName, nameof(indexName)); + Argument.AssertNotNull(authentication, nameof(authentication)); + Argument.AssertNotNull(embeddingDependency, nameof(embeddingDependency)); + Argument.AssertNotNull(fieldMappings, nameof(fieldMappings)); + + _internalIncludeContexts = new ChangeTrackingList(); + Endpoint = endpoint; + DatabaseName = databaseName; + CollectionName = collectionName; + AppName = appName; + IndexName = indexName; + Authentication = authentication; + EmbeddingDependency = embeddingDependency; + FieldMappings = fieldMappings; + } + + /// Initializes a new instance of . + /// The configured number of documents to feature in the query. + /// Whether queries should be restricted to use of the indexed data. + /// + /// The configured strictness of the search relevance filtering. + /// Higher strictness will increase precision but lower recall of the answer. + /// + /// + /// The maximum number of rewritten queries that should be sent to the search provider for a single user message. + /// By default, the system will make an automatic determination. + /// + /// + /// If set to true, the system will allow partial search results to be used and the request will fail if all + /// partial queries fail. If not specified or specified as false, the request will fail if any search query fails. + /// + /// + /// The output context properties to include on the response. + /// By default, citations and intent will be requested. + /// + /// The name of the MongoDB cluster endpoint. + /// The name of the MongoDB database. + /// The name of the MongoDB collection. + /// The name of the MongoDB application. + /// The name of the MongoDB index. + /// + /// The authentication mechanism to use with Pinecone. + /// Supported authentication mechanisms for Pinecone include: username and password. + /// Please note is the base class. According to the scenario, a derived class of the base class might need to be assigned here, or this property needs to be casted to one of the possible derived classes.. + /// + /// + /// The vectorization source to use as an embedding dependency for the MongoDB data source. + /// Supported vectorization sources for MongoDB include: endpoint, deployment name. + /// Please note is the base class. According to the scenario, a derived class of the base class might need to be assigned here, or this property needs to be casted to one of the possible derived classes.. + /// + /// + /// Field mappings to apply to data used by the MongoDB data source. + /// Note that content and vector field mappings are required for MongoDB. + /// + /// Keeps track of any properties unknown to the library. + internal InternalMongoDBChatDataSourceParameters(int? topNDocuments, bool? inScope, int? strictness, int? maxSearchQueries, bool? allowPartialResult, IList internalIncludeContexts, string endpoint, string databaseName, string collectionName, string appName, string indexName, DataSourceAuthentication authentication, DataSourceVectorizer embeddingDependency, DataSourceFieldMappings fieldMappings, IDictionary serializedAdditionalRawData) + { + TopNDocuments = topNDocuments; + InScope = inScope; + Strictness = strictness; + MaxSearchQueries = maxSearchQueries; + AllowPartialResult = allowPartialResult; + _internalIncludeContexts = internalIncludeContexts; + Endpoint = endpoint; + DatabaseName = databaseName; + CollectionName = collectionName; + AppName = appName; + IndexName = indexName; + Authentication = authentication; + EmbeddingDependency = embeddingDependency; + FieldMappings = fieldMappings; + SerializedAdditionalRawData = serializedAdditionalRawData; + } + + /// Initializes a new instance of for deserialization. + internal InternalMongoDBChatDataSourceParameters() + { + } + + /// The configured number of documents to feature in the query. + public int? TopNDocuments { get; set; } + /// Whether queries should be restricted to use of the indexed data. + public bool? InScope { get; set; } + /// + /// The configured strictness of the search relevance filtering. + /// Higher strictness will increase precision but lower recall of the answer. + /// + public int? Strictness { get; set; } + /// + /// The maximum number of rewritten queries that should be sent to the search provider for a single user message. + /// By default, the system will make an automatic determination. + /// + public int? MaxSearchQueries { get; set; } + /// + /// If set to true, the system will allow partial search results to be used and the request will fail if all + /// partial queries fail. If not specified or specified as false, the request will fail if any search query fails. + /// + public bool? AllowPartialResult { get; set; } + /// The name of the MongoDB cluster endpoint. + internal string Endpoint { get; set; } + /// The name of the MongoDB database. + internal string DatabaseName { get; set; } + /// The name of the MongoDB collection. + internal string CollectionName { get; set; } + /// The name of the MongoDB application. + internal string AppName { get; set; } + /// The name of the MongoDB index. + internal string IndexName { get; set; } + } +} + diff --git a/sdk/openai/Azure.AI.OpenAI/src/Generated/InternalPineconeChatDataSourceParameters.Serialization.cs b/sdk/openai/Azure.AI.OpenAI/src/Generated/InternalPineconeChatDataSourceParameters.Serialization.cs index e7acec9ad698..9e985538ecb7 100644 --- a/sdk/openai/Azure.AI.OpenAI/src/Generated/InternalPineconeChatDataSourceParameters.Serialization.cs +++ b/sdk/openai/Azure.AI.OpenAI/src/Generated/InternalPineconeChatDataSourceParameters.Serialization.cs @@ -36,11 +36,6 @@ void IJsonModel.Write(Utf8JsonWriter w writer.WritePropertyName("strictness"u8); writer.WriteNumberValue(Strictness.Value); } - if (SerializedAdditionalRawData?.ContainsKey("role_information") != true && Optional.IsDefined(RoleInformation)) - { - writer.WritePropertyName("role_information"u8); - writer.WriteStringValue(RoleInformation); - } if (SerializedAdditionalRawData?.ContainsKey("max_search_queries") != true && Optional.IsDefined(MaxSearchQueries)) { writer.WritePropertyName("max_search_queries"u8); @@ -131,7 +126,6 @@ internal static InternalPineconeChatDataSourceParameters DeserializeInternalPine int? topNDocuments = default; bool? inScope = default; int? strictness = default; - string roleInformation = default; int? maxSearchQueries = default; bool? allowPartialResult = default; IList includeContexts = default; @@ -171,11 +165,6 @@ internal static InternalPineconeChatDataSourceParameters DeserializeInternalPine strictness = property.Value.GetInt32(); continue; } - if (property.NameEquals("role_information"u8)) - { - roleInformation = property.Value.GetString(); - continue; - } if (property.NameEquals("max_search_queries"u8)) { if (property.Value.ValueKind == JsonValueKind.Null) @@ -244,7 +233,6 @@ internal static InternalPineconeChatDataSourceParameters DeserializeInternalPine topNDocuments, inScope, strictness, - roleInformation, maxSearchQueries, allowPartialResult, includeContexts ?? new ChangeTrackingList(), diff --git a/sdk/openai/Azure.AI.OpenAI/src/Generated/InternalPineconeChatDataSourceParameters.cs b/sdk/openai/Azure.AI.OpenAI/src/Generated/InternalPineconeChatDataSourceParameters.cs index 2e19d59b5e7e..c886686b184b 100644 --- a/sdk/openai/Azure.AI.OpenAI/src/Generated/InternalPineconeChatDataSourceParameters.cs +++ b/sdk/openai/Azure.AI.OpenAI/src/Generated/InternalPineconeChatDataSourceParameters.cs @@ -59,7 +59,7 @@ internal partial class InternalPineconeChatDataSourceParameters /// Note that content field mappings are required for Pinecone. /// /// , , , or is null. - internal InternalPineconeChatDataSourceParameters(string environment, string indexName, DataSourceAuthentication authentication, DataSourceVectorizer vectorizationSource, DataSourceFieldMappings fieldMappings) + public InternalPineconeChatDataSourceParameters(string environment, string indexName, DataSourceAuthentication authentication, DataSourceVectorizer vectorizationSource, DataSourceFieldMappings fieldMappings) { Argument.AssertNotNull(environment, nameof(environment)); Argument.AssertNotNull(indexName, nameof(indexName)); @@ -82,11 +82,6 @@ internal InternalPineconeChatDataSourceParameters(string environment, string ind /// The configured strictness of the search relevance filtering. /// Higher strictness will increase precision but lower recall of the answer. /// - /// - /// Additional instructions for the model to inform how it should behave and any context it should reference when - /// generating a response. You can describe the assistant's personality and tell it how to format responses. - /// This is limited to 100 tokens and counts against the overall token limit. - /// /// /// The maximum number of rewritten queries that should be sent to the search provider for a single user message. /// By default, the system will make an automatic determination. @@ -116,12 +111,11 @@ internal InternalPineconeChatDataSourceParameters(string environment, string ind /// Note that content field mappings are required for Pinecone. /// /// Keeps track of any properties unknown to the library. - internal InternalPineconeChatDataSourceParameters(int? topNDocuments, bool? inScope, int? strictness, string roleInformation, int? maxSearchQueries, bool? allowPartialResult, IList internalIncludeContexts, string environment, string indexName, DataSourceAuthentication authentication, DataSourceVectorizer vectorizationSource, DataSourceFieldMappings fieldMappings, IDictionary serializedAdditionalRawData) + internal InternalPineconeChatDataSourceParameters(int? topNDocuments, bool? inScope, int? strictness, int? maxSearchQueries, bool? allowPartialResult, IList internalIncludeContexts, string environment, string indexName, DataSourceAuthentication authentication, DataSourceVectorizer vectorizationSource, DataSourceFieldMappings fieldMappings, IDictionary serializedAdditionalRawData) { TopNDocuments = topNDocuments; InScope = inScope; Strictness = strictness; - RoleInformation = roleInformation; MaxSearchQueries = maxSearchQueries; AllowPartialResult = allowPartialResult; _internalIncludeContexts = internalIncludeContexts; @@ -139,30 +133,24 @@ internal InternalPineconeChatDataSourceParameters() } /// The configured number of documents to feature in the query. - internal int? TopNDocuments { get; set; } + public int? TopNDocuments { get; set; } /// Whether queries should be restricted to use of the indexed data. - internal bool? InScope { get; set; } + public bool? InScope { get; set; } /// /// The configured strictness of the search relevance filtering. /// Higher strictness will increase precision but lower recall of the answer. /// - internal int? Strictness { get; set; } - /// - /// Additional instructions for the model to inform how it should behave and any context it should reference when - /// generating a response. You can describe the assistant's personality and tell it how to format responses. - /// This is limited to 100 tokens and counts against the overall token limit. - /// - internal string RoleInformation { get; set; } + public int? Strictness { get; set; } /// /// The maximum number of rewritten queries that should be sent to the search provider for a single user message. /// By default, the system will make an automatic determination. /// - internal int? MaxSearchQueries { get; set; } + public int? MaxSearchQueries { get; set; } /// /// If set to true, the system will allow partial search results to be used and the request will fail if all /// partial queries fail. If not specified or specified as false, the request will fail if any search query fails. /// - internal bool? AllowPartialResult { get; set; } + public bool? AllowPartialResult { get; set; } /// The environment name to use with Pinecone. internal string Environment { get; set; } /// The name of the Pinecone database index to use. diff --git a/sdk/openai/Azure.AI.OpenAI/src/Generated/AzureMachineLearningIndexChatDataSource.Serialization.cs b/sdk/openai/Azure.AI.OpenAI/src/Generated/MongoDBChatDataSource.Serialization.cs similarity index 58% rename from sdk/openai/Azure.AI.OpenAI/src/Generated/AzureMachineLearningIndexChatDataSource.Serialization.cs rename to sdk/openai/Azure.AI.OpenAI/src/Generated/MongoDBChatDataSource.Serialization.cs index 2384629e5184..f3101a5b54ed 100644 --- a/sdk/openai/Azure.AI.OpenAI/src/Generated/AzureMachineLearningIndexChatDataSource.Serialization.cs +++ b/sdk/openai/Azure.AI.OpenAI/src/Generated/MongoDBChatDataSource.Serialization.cs @@ -10,21 +10,21 @@ namespace Azure.AI.OpenAI.Chat { - public partial class AzureMachineLearningIndexChatDataSource : IJsonModel + public partial class MongoDBChatDataSource : IJsonModel { - void IJsonModel.Write(Utf8JsonWriter writer, ModelReaderWriterOptions options) + void IJsonModel.Write(Utf8JsonWriter writer, ModelReaderWriterOptions options) { - var format = options.Format == "W" ? ((IPersistableModel)this).GetFormatFromOptions(options) : options.Format; + var format = options.Format == "W" ? ((IPersistableModel)this).GetFormatFromOptions(options) : options.Format; if (format != "J") { - throw new FormatException($"The model {nameof(AzureMachineLearningIndexChatDataSource)} does not support writing '{format}' format."); + throw new FormatException($"The model {nameof(MongoDBChatDataSource)} does not support writing '{format}' format."); } writer.WriteStartObject(); if (SerializedAdditionalRawData?.ContainsKey("parameters") != true) { writer.WritePropertyName("parameters"u8); - writer.WriteObjectValue(InternalParameters, options); + writer.WriteObjectValue(InternalParameters, options); } if (SerializedAdditionalRawData?.ContainsKey("type") != true) { @@ -53,19 +53,19 @@ void IJsonModel.Write(Utf8JsonWriter wr writer.WriteEndObject(); } - AzureMachineLearningIndexChatDataSource IJsonModel.Create(ref Utf8JsonReader reader, ModelReaderWriterOptions options) + MongoDBChatDataSource IJsonModel.Create(ref Utf8JsonReader reader, ModelReaderWriterOptions options) { - var format = options.Format == "W" ? ((IPersistableModel)this).GetFormatFromOptions(options) : options.Format; + var format = options.Format == "W" ? ((IPersistableModel)this).GetFormatFromOptions(options) : options.Format; if (format != "J") { - throw new FormatException($"The model {nameof(AzureMachineLearningIndexChatDataSource)} does not support reading '{format}' format."); + throw new FormatException($"The model {nameof(MongoDBChatDataSource)} does not support reading '{format}' format."); } using JsonDocument document = JsonDocument.ParseValue(ref reader); - return DeserializeAzureMachineLearningIndexChatDataSource(document.RootElement, options); + return DeserializeMongoDBChatDataSource(document.RootElement, options); } - internal static AzureMachineLearningIndexChatDataSource DeserializeAzureMachineLearningIndexChatDataSource(JsonElement element, ModelReaderWriterOptions options = null) + internal static MongoDBChatDataSource DeserializeMongoDBChatDataSource(JsonElement element, ModelReaderWriterOptions options = null) { options ??= ModelSerializationExtensions.WireOptions; @@ -73,7 +73,7 @@ internal static AzureMachineLearningIndexChatDataSource DeserializeAzureMachineL { return null; } - InternalAzureMachineLearningIndexChatDataSourceParameters parameters = default; + InternalMongoDBChatDataSourceParameters parameters = default; string type = default; IDictionary serializedAdditionalRawData = default; Dictionary rawDataDictionary = new Dictionary(); @@ -81,7 +81,7 @@ internal static AzureMachineLearningIndexChatDataSource DeserializeAzureMachineL { if (property.NameEquals("parameters"u8)) { - parameters = InternalAzureMachineLearningIndexChatDataSourceParameters.DeserializeInternalAzureMachineLearningIndexChatDataSourceParameters(property.Value, options); + parameters = InternalMongoDBChatDataSourceParameters.DeserializeInternalMongoDBChatDataSourceParameters(property.Value, options); continue; } if (property.NameEquals("type"u8)) @@ -96,46 +96,46 @@ internal static AzureMachineLearningIndexChatDataSource DeserializeAzureMachineL } } serializedAdditionalRawData = rawDataDictionary; - return new AzureMachineLearningIndexChatDataSource(type, serializedAdditionalRawData, parameters); + return new MongoDBChatDataSource(type, serializedAdditionalRawData, parameters); } - BinaryData IPersistableModel.Write(ModelReaderWriterOptions options) + BinaryData IPersistableModel.Write(ModelReaderWriterOptions options) { - var format = options.Format == "W" ? ((IPersistableModel)this).GetFormatFromOptions(options) : options.Format; + var format = options.Format == "W" ? ((IPersistableModel)this).GetFormatFromOptions(options) : options.Format; switch (format) { case "J": return ModelReaderWriter.Write(this, options); default: - throw new FormatException($"The model {nameof(AzureMachineLearningIndexChatDataSource)} does not support writing '{options.Format}' format."); + throw new FormatException($"The model {nameof(MongoDBChatDataSource)} does not support writing '{options.Format}' format."); } } - AzureMachineLearningIndexChatDataSource IPersistableModel.Create(BinaryData data, ModelReaderWriterOptions options) + MongoDBChatDataSource IPersistableModel.Create(BinaryData data, ModelReaderWriterOptions options) { - var format = options.Format == "W" ? ((IPersistableModel)this).GetFormatFromOptions(options) : options.Format; + var format = options.Format == "W" ? ((IPersistableModel)this).GetFormatFromOptions(options) : options.Format; switch (format) { case "J": { using JsonDocument document = JsonDocument.Parse(data); - return DeserializeAzureMachineLearningIndexChatDataSource(document.RootElement, options); + return DeserializeMongoDBChatDataSource(document.RootElement, options); } default: - throw new FormatException($"The model {nameof(AzureMachineLearningIndexChatDataSource)} does not support reading '{options.Format}' format."); + throw new FormatException($"The model {nameof(MongoDBChatDataSource)} does not support reading '{options.Format}' format."); } } - string IPersistableModel.GetFormatFromOptions(ModelReaderWriterOptions options) => "J"; + string IPersistableModel.GetFormatFromOptions(ModelReaderWriterOptions options) => "J"; /// Deserializes the model from a raw response. /// The result to deserialize the model from. - internal static new AzureMachineLearningIndexChatDataSource FromResponse(PipelineResponse response) + internal static new MongoDBChatDataSource FromResponse(PipelineResponse response) { using var document = JsonDocument.Parse(response.Content); - return DeserializeAzureMachineLearningIndexChatDataSource(document.RootElement); + return DeserializeMongoDBChatDataSource(document.RootElement); } /// Convert into a . diff --git a/sdk/openai/Azure.AI.OpenAI/src/Generated/MongoDBChatDataSource.cs b/sdk/openai/Azure.AI.OpenAI/src/Generated/MongoDBChatDataSource.cs new file mode 100644 index 000000000000..c673580c2205 --- /dev/null +++ b/sdk/openai/Azure.AI.OpenAI/src/Generated/MongoDBChatDataSource.cs @@ -0,0 +1,14 @@ +// + +#nullable disable + +using System; +using System.Collections.Generic; + +namespace Azure.AI.OpenAI.Chat +{ + /// The MongoDBChatDataSource. + public partial class MongoDBChatDataSource : AzureChatDataSource + { + } +} diff --git a/sdk/openai/Azure.AI.OpenAI/src/Generated/RequestContentFilterResult.Serialization.cs b/sdk/openai/Azure.AI.OpenAI/src/Generated/RequestContentFilterResult.Serialization.cs new file mode 100644 index 000000000000..030bb75bd3c8 --- /dev/null +++ b/sdk/openai/Azure.AI.OpenAI/src/Generated/RequestContentFilterResult.Serialization.cs @@ -0,0 +1,155 @@ +// + +#nullable disable + +using System; +using System.ClientModel; +using System.ClientModel.Primitives; +using System.Collections.Generic; +using System.Text.Json; + +namespace Azure.AI.OpenAI +{ + public partial class RequestContentFilterResult : IJsonModel + { + void IJsonModel.Write(Utf8JsonWriter writer, ModelReaderWriterOptions options) + { + var format = options.Format == "W" ? ((IPersistableModel)this).GetFormatFromOptions(options) : options.Format; + if (format != "J") + { + throw new FormatException($"The model {nameof(RequestContentFilterResult)} does not support writing '{format}' format."); + } + + writer.WriteStartObject(); + if (SerializedAdditionalRawData?.ContainsKey("prompt_index") != true && Optional.IsDefined(PromptIndex)) + { + writer.WritePropertyName("prompt_index"u8); + writer.WriteNumberValue(PromptIndex.Value); + } + if (SerializedAdditionalRawData?.ContainsKey("content_filter_results") != true && Optional.IsDefined(InternalResults)) + { + writer.WritePropertyName("content_filter_results"u8); + writer.WriteObjectValue(InternalResults, options); + } + if (SerializedAdditionalRawData != null) + { + foreach (var item in SerializedAdditionalRawData) + { + if (ModelSerializationExtensions.IsSentinelValue(item.Value)) + { + continue; + } + writer.WritePropertyName(item.Key); +#if NET6_0_OR_GREATER + writer.WriteRawValue(item.Value); +#else + using (JsonDocument document = JsonDocument.Parse(item.Value)) + { + JsonSerializer.Serialize(writer, document.RootElement); + } +#endif + } + } + writer.WriteEndObject(); + } + + RequestContentFilterResult IJsonModel.Create(ref Utf8JsonReader reader, ModelReaderWriterOptions options) + { + var format = options.Format == "W" ? ((IPersistableModel)this).GetFormatFromOptions(options) : options.Format; + if (format != "J") + { + throw new FormatException($"The model {nameof(RequestContentFilterResult)} does not support reading '{format}' format."); + } + + using JsonDocument document = JsonDocument.ParseValue(ref reader); + return DeserializeRequestContentFilterResult(document.RootElement, options); + } + + internal static RequestContentFilterResult DeserializeRequestContentFilterResult(JsonElement element, ModelReaderWriterOptions options = null) + { + options ??= ModelSerializationExtensions.WireOptions; + + if (element.ValueKind == JsonValueKind.Null) + { + return null; + } + int? promptIndex = default; + InternalAzureContentFilterResultForPromptContentFilterResults contentFilterResults = default; + IDictionary serializedAdditionalRawData = default; + Dictionary rawDataDictionary = new Dictionary(); + foreach (var property in element.EnumerateObject()) + { + if (property.NameEquals("prompt_index"u8)) + { + if (property.Value.ValueKind == JsonValueKind.Null) + { + continue; + } + promptIndex = property.Value.GetInt32(); + continue; + } + if (property.NameEquals("content_filter_results"u8)) + { + if (property.Value.ValueKind == JsonValueKind.Null) + { + continue; + } + contentFilterResults = InternalAzureContentFilterResultForPromptContentFilterResults.DeserializeInternalAzureContentFilterResultForPromptContentFilterResults(property.Value, options); + continue; + } + if (options.Format != "W") + { + rawDataDictionary ??= new Dictionary(); + rawDataDictionary.Add(property.Name, BinaryData.FromString(property.Value.GetRawText())); + } + } + serializedAdditionalRawData = rawDataDictionary; + return new RequestContentFilterResult(promptIndex, contentFilterResults, serializedAdditionalRawData); + } + + BinaryData IPersistableModel.Write(ModelReaderWriterOptions options) + { + var format = options.Format == "W" ? ((IPersistableModel)this).GetFormatFromOptions(options) : options.Format; + + switch (format) + { + case "J": + return ModelReaderWriter.Write(this, options); + default: + throw new FormatException($"The model {nameof(RequestContentFilterResult)} does not support writing '{options.Format}' format."); + } + } + + RequestContentFilterResult IPersistableModel.Create(BinaryData data, ModelReaderWriterOptions options) + { + var format = options.Format == "W" ? ((IPersistableModel)this).GetFormatFromOptions(options) : options.Format; + + switch (format) + { + case "J": + { + using JsonDocument document = JsonDocument.Parse(data); + return DeserializeRequestContentFilterResult(document.RootElement, options); + } + default: + throw new FormatException($"The model {nameof(RequestContentFilterResult)} does not support reading '{options.Format}' format."); + } + } + + string IPersistableModel.GetFormatFromOptions(ModelReaderWriterOptions options) => "J"; + + /// Deserializes the model from a raw response. + /// The result to deserialize the model from. + internal static RequestContentFilterResult FromResponse(PipelineResponse response) + { + using var document = JsonDocument.Parse(response.Content); + return DeserializeRequestContentFilterResult(document.RootElement); + } + + /// Convert into a . + internal virtual BinaryContent ToBinaryContent() + { + return BinaryContent.Create(this, ModelSerializationExtensions.WireOptions); + } + } +} diff --git a/sdk/openai/Azure.AI.OpenAI/src/Generated/ContentFilterResultForPrompt.cs b/sdk/openai/Azure.AI.OpenAI/src/Generated/RequestContentFilterResult.cs similarity index 80% rename from sdk/openai/Azure.AI.OpenAI/src/Generated/ContentFilterResultForPrompt.cs rename to sdk/openai/Azure.AI.OpenAI/src/Generated/RequestContentFilterResult.cs index 46aa27b09f48..74a54e0155bb 100644 --- a/sdk/openai/Azure.AI.OpenAI/src/Generated/ContentFilterResultForPrompt.cs +++ b/sdk/openai/Azure.AI.OpenAI/src/Generated/RequestContentFilterResult.cs @@ -8,7 +8,7 @@ namespace Azure.AI.OpenAI { /// A content filter result associated with a single input prompt item into a generative AI system. - public partial class ContentFilterResultForPrompt + public partial class RequestContentFilterResult { /// /// Keeps track of any properties unknown to the library. @@ -41,16 +41,16 @@ public partial class ContentFilterResultForPrompt /// /// internal IDictionary SerializedAdditionalRawData { get; set; } - /// Initializes a new instance of . - internal ContentFilterResultForPrompt() + /// Initializes a new instance of . + internal RequestContentFilterResult() { } - /// Initializes a new instance of . + /// Initializes a new instance of . /// The index of the input prompt associated with the accompanying content filter result categories. /// The content filter category details for the result. /// Keeps track of any properties unknown to the library. - internal ContentFilterResultForPrompt(int? promptIndex, InternalAzureContentFilterResultForPromptContentFilterResults internalResults, IDictionary serializedAdditionalRawData) + internal RequestContentFilterResult(int? promptIndex, InternalAzureContentFilterResultForPromptContentFilterResults internalResults, IDictionary serializedAdditionalRawData) { PromptIndex = promptIndex; InternalResults = internalResults; diff --git a/sdk/openai/Azure.AI.OpenAI/src/Generated/ImageContentFilterResultForPrompt.Serialization.cs b/sdk/openai/Azure.AI.OpenAI/src/Generated/RequestImageContentFilterResult.Serialization.cs similarity index 78% rename from sdk/openai/Azure.AI.OpenAI/src/Generated/ImageContentFilterResultForPrompt.Serialization.cs rename to sdk/openai/Azure.AI.OpenAI/src/Generated/RequestImageContentFilterResult.Serialization.cs index 1ecef8716b97..150a5f9d7775 100644 --- a/sdk/openai/Azure.AI.OpenAI/src/Generated/ImageContentFilterResultForPrompt.Serialization.cs +++ b/sdk/openai/Azure.AI.OpenAI/src/Generated/RequestImageContentFilterResult.Serialization.cs @@ -10,14 +10,14 @@ namespace Azure.AI.OpenAI { - public partial class ImageContentFilterResultForPrompt : IJsonModel + public partial class RequestImageContentFilterResult : IJsonModel { - void IJsonModel.Write(Utf8JsonWriter writer, ModelReaderWriterOptions options) + void IJsonModel.Write(Utf8JsonWriter writer, ModelReaderWriterOptions options) { - var format = options.Format == "W" ? ((IPersistableModel)this).GetFormatFromOptions(options) : options.Format; + var format = options.Format == "W" ? ((IPersistableModel)this).GetFormatFromOptions(options) : options.Format; if (format != "J") { - throw new FormatException($"The model {nameof(ImageContentFilterResultForPrompt)} does not support writing '{format}' format."); + throw new FormatException($"The model {nameof(RequestImageContentFilterResult)} does not support writing '{format}' format."); } writer.WriteStartObject(); @@ -78,19 +78,19 @@ void IJsonModel.Write(Utf8JsonWriter writer, writer.WriteEndObject(); } - ImageContentFilterResultForPrompt IJsonModel.Create(ref Utf8JsonReader reader, ModelReaderWriterOptions options) + RequestImageContentFilterResult IJsonModel.Create(ref Utf8JsonReader reader, ModelReaderWriterOptions options) { - var format = options.Format == "W" ? ((IPersistableModel)this).GetFormatFromOptions(options) : options.Format; + var format = options.Format == "W" ? ((IPersistableModel)this).GetFormatFromOptions(options) : options.Format; if (format != "J") { - throw new FormatException($"The model {nameof(ImageContentFilterResultForPrompt)} does not support reading '{format}' format."); + throw new FormatException($"The model {nameof(RequestImageContentFilterResult)} does not support reading '{format}' format."); } using JsonDocument document = JsonDocument.ParseValue(ref reader); - return DeserializeImageContentFilterResultForPrompt(document.RootElement, options); + return DeserializeRequestImageContentFilterResult(document.RootElement, options); } - internal static ImageContentFilterResultForPrompt DeserializeImageContentFilterResultForPrompt(JsonElement element, ModelReaderWriterOptions options = null) + internal static RequestImageContentFilterResult DeserializeRequestImageContentFilterResult(JsonElement element, ModelReaderWriterOptions options = null) { options ??= ModelSerializationExtensions.WireOptions; @@ -175,7 +175,7 @@ internal static ImageContentFilterResultForPrompt DeserializeImageContentFilterR } } serializedAdditionalRawData = rawDataDictionary; - return new ImageContentFilterResultForPrompt( + return new RequestImageContentFilterResult( sexual, violence, hate, @@ -186,43 +186,43 @@ internal static ImageContentFilterResultForPrompt DeserializeImageContentFilterR jailbreak); } - BinaryData IPersistableModel.Write(ModelReaderWriterOptions options) + BinaryData IPersistableModel.Write(ModelReaderWriterOptions options) { - var format = options.Format == "W" ? ((IPersistableModel)this).GetFormatFromOptions(options) : options.Format; + var format = options.Format == "W" ? ((IPersistableModel)this).GetFormatFromOptions(options) : options.Format; switch (format) { case "J": return ModelReaderWriter.Write(this, options); default: - throw new FormatException($"The model {nameof(ImageContentFilterResultForPrompt)} does not support writing '{options.Format}' format."); + throw new FormatException($"The model {nameof(RequestImageContentFilterResult)} does not support writing '{options.Format}' format."); } } - ImageContentFilterResultForPrompt IPersistableModel.Create(BinaryData data, ModelReaderWriterOptions options) + RequestImageContentFilterResult IPersistableModel.Create(BinaryData data, ModelReaderWriterOptions options) { - var format = options.Format == "W" ? ((IPersistableModel)this).GetFormatFromOptions(options) : options.Format; + var format = options.Format == "W" ? ((IPersistableModel)this).GetFormatFromOptions(options) : options.Format; switch (format) { case "J": { using JsonDocument document = JsonDocument.Parse(data); - return DeserializeImageContentFilterResultForPrompt(document.RootElement, options); + return DeserializeRequestImageContentFilterResult(document.RootElement, options); } default: - throw new FormatException($"The model {nameof(ImageContentFilterResultForPrompt)} does not support reading '{options.Format}' format."); + throw new FormatException($"The model {nameof(RequestImageContentFilterResult)} does not support reading '{options.Format}' format."); } } - string IPersistableModel.GetFormatFromOptions(ModelReaderWriterOptions options) => "J"; + string IPersistableModel.GetFormatFromOptions(ModelReaderWriterOptions options) => "J"; /// Deserializes the model from a raw response. /// The result to deserialize the model from. - internal static new ImageContentFilterResultForPrompt FromResponse(PipelineResponse response) + internal static new RequestImageContentFilterResult FromResponse(PipelineResponse response) { using var document = JsonDocument.Parse(response.Content); - return DeserializeImageContentFilterResultForPrompt(document.RootElement); + return DeserializeRequestImageContentFilterResult(document.RootElement); } /// Convert into a . diff --git a/sdk/openai/Azure.AI.OpenAI/src/Generated/ImageContentFilterResultForPrompt.cs b/sdk/openai/Azure.AI.OpenAI/src/Generated/RequestImageContentFilterResult.cs similarity index 79% rename from sdk/openai/Azure.AI.OpenAI/src/Generated/ImageContentFilterResultForPrompt.cs rename to sdk/openai/Azure.AI.OpenAI/src/Generated/RequestImageContentFilterResult.cs index 86b7f00cc3c3..e41fc322b0ee 100644 --- a/sdk/openai/Azure.AI.OpenAI/src/Generated/ImageContentFilterResultForPrompt.cs +++ b/sdk/openai/Azure.AI.OpenAI/src/Generated/RequestImageContentFilterResult.cs @@ -8,23 +8,23 @@ namespace Azure.AI.OpenAI { /// A content filter result for an image generation operation's input request content. - public partial class ImageContentFilterResultForPrompt : ImageContentFilterResultForResponse + public partial class RequestImageContentFilterResult : ResponseImageContentFilterResult { - /// Initializes a new instance of . + /// Initializes a new instance of . /// /// A detection result that describes user prompt injection attacks, where malicious users deliberately exploit /// system vulnerabilities to elicit unauthorized behavior from the LLM. This could lead to inappropriate content /// generation or violations of system-imposed restrictions. /// /// is null. - internal ImageContentFilterResultForPrompt(ContentFilterDetectionResult jailbreak) + internal RequestImageContentFilterResult(ContentFilterDetectionResult jailbreak) { Argument.AssertNotNull(jailbreak, nameof(jailbreak)); Jailbreak = jailbreak; } - /// Initializes a new instance of . + /// Initializes a new instance of . /// /// A content filter category for language related to anatomical organs and genitals, romantic relationships, acts /// portrayed in erotic or affectionate terms, pregnancy, physical sexual acts, including those portrayed as an @@ -56,15 +56,15 @@ internal ImageContentFilterResultForPrompt(ContentFilterDetectionResult jailbrea /// system vulnerabilities to elicit unauthorized behavior from the LLM. This could lead to inappropriate content /// generation or violations of system-imposed restrictions. /// - internal ImageContentFilterResultForPrompt(ContentFilterSeverityResult sexual, ContentFilterSeverityResult violence, ContentFilterSeverityResult hate, ContentFilterSeverityResult selfHarm, IDictionary serializedAdditionalRawData, ContentFilterDetectionResult profanity, ContentFilterBlocklistResult customBlocklists, ContentFilterDetectionResult jailbreak) : base(sexual, violence, hate, selfHarm, serializedAdditionalRawData) + internal RequestImageContentFilterResult(ContentFilterSeverityResult sexual, ContentFilterSeverityResult violence, ContentFilterSeverityResult hate, ContentFilterSeverityResult selfHarm, IDictionary serializedAdditionalRawData, ContentFilterDetectionResult profanity, ContentFilterBlocklistResult customBlocklists, ContentFilterDetectionResult jailbreak) : base(sexual, violence, hate, selfHarm, serializedAdditionalRawData) { Profanity = profanity; CustomBlocklists = customBlocklists; Jailbreak = jailbreak; } - /// Initializes a new instance of for deserialization. - internal ImageContentFilterResultForPrompt() + /// Initializes a new instance of for deserialization. + internal RequestImageContentFilterResult() { } diff --git a/sdk/openai/Azure.AI.OpenAI/src/Generated/ContentFilterResultForResponse.Serialization.cs b/sdk/openai/Azure.AI.OpenAI/src/Generated/ResponseContentFilterResult.Serialization.cs similarity index 82% rename from sdk/openai/Azure.AI.OpenAI/src/Generated/ContentFilterResultForResponse.Serialization.cs rename to sdk/openai/Azure.AI.OpenAI/src/Generated/ResponseContentFilterResult.Serialization.cs index 5b2644c9cdc5..5e9da43d62eb 100644 --- a/sdk/openai/Azure.AI.OpenAI/src/Generated/ContentFilterResultForResponse.Serialization.cs +++ b/sdk/openai/Azure.AI.OpenAI/src/Generated/ResponseContentFilterResult.Serialization.cs @@ -10,14 +10,14 @@ namespace Azure.AI.OpenAI { - public partial class ContentFilterResultForResponse : IJsonModel + public partial class ResponseContentFilterResult : IJsonModel { - void IJsonModel.Write(Utf8JsonWriter writer, ModelReaderWriterOptions options) + void IJsonModel.Write(Utf8JsonWriter writer, ModelReaderWriterOptions options) { - var format = options.Format == "W" ? ((IPersistableModel)this).GetFormatFromOptions(options) : options.Format; + var format = options.Format == "W" ? ((IPersistableModel)this).GetFormatFromOptions(options) : options.Format; if (format != "J") { - throw new FormatException($"The model {nameof(ContentFilterResultForResponse)} does not support writing '{format}' format."); + throw new FormatException($"The model {nameof(ResponseContentFilterResult)} does not support writing '{format}' format."); } writer.WriteStartObject(); @@ -88,19 +88,19 @@ void IJsonModel.Write(Utf8JsonWriter writer, Mod writer.WriteEndObject(); } - ContentFilterResultForResponse IJsonModel.Create(ref Utf8JsonReader reader, ModelReaderWriterOptions options) + ResponseContentFilterResult IJsonModel.Create(ref Utf8JsonReader reader, ModelReaderWriterOptions options) { - var format = options.Format == "W" ? ((IPersistableModel)this).GetFormatFromOptions(options) : options.Format; + var format = options.Format == "W" ? ((IPersistableModel)this).GetFormatFromOptions(options) : options.Format; if (format != "J") { - throw new FormatException($"The model {nameof(ContentFilterResultForResponse)} does not support reading '{format}' format."); + throw new FormatException($"The model {nameof(ResponseContentFilterResult)} does not support reading '{format}' format."); } using JsonDocument document = JsonDocument.ParseValue(ref reader); - return DeserializeContentFilterResultForResponse(document.RootElement, options); + return DeserializeResponseContentFilterResult(document.RootElement, options); } - internal static ContentFilterResultForResponse DeserializeContentFilterResultForResponse(JsonElement element, ModelReaderWriterOptions options = null) + internal static ResponseContentFilterResult DeserializeResponseContentFilterResult(JsonElement element, ModelReaderWriterOptions options = null) { options ??= ModelSerializationExtensions.WireOptions; @@ -209,7 +209,7 @@ internal static ContentFilterResultForResponse DeserializeContentFilterResultFor } } serializedAdditionalRawData = rawDataDictionary; - return new ContentFilterResultForResponse( + return new ResponseContentFilterResult( sexual, hate, violence, @@ -222,43 +222,43 @@ internal static ContentFilterResultForResponse DeserializeContentFilterResultFor serializedAdditionalRawData); } - BinaryData IPersistableModel.Write(ModelReaderWriterOptions options) + BinaryData IPersistableModel.Write(ModelReaderWriterOptions options) { - var format = options.Format == "W" ? ((IPersistableModel)this).GetFormatFromOptions(options) : options.Format; + var format = options.Format == "W" ? ((IPersistableModel)this).GetFormatFromOptions(options) : options.Format; switch (format) { case "J": return ModelReaderWriter.Write(this, options); default: - throw new FormatException($"The model {nameof(ContentFilterResultForResponse)} does not support writing '{options.Format}' format."); + throw new FormatException($"The model {nameof(ResponseContentFilterResult)} does not support writing '{options.Format}' format."); } } - ContentFilterResultForResponse IPersistableModel.Create(BinaryData data, ModelReaderWriterOptions options) + ResponseContentFilterResult IPersistableModel.Create(BinaryData data, ModelReaderWriterOptions options) { - var format = options.Format == "W" ? ((IPersistableModel)this).GetFormatFromOptions(options) : options.Format; + var format = options.Format == "W" ? ((IPersistableModel)this).GetFormatFromOptions(options) : options.Format; switch (format) { case "J": { using JsonDocument document = JsonDocument.Parse(data); - return DeserializeContentFilterResultForResponse(document.RootElement, options); + return DeserializeResponseContentFilterResult(document.RootElement, options); } default: - throw new FormatException($"The model {nameof(ContentFilterResultForResponse)} does not support reading '{options.Format}' format."); + throw new FormatException($"The model {nameof(ResponseContentFilterResult)} does not support reading '{options.Format}' format."); } } - string IPersistableModel.GetFormatFromOptions(ModelReaderWriterOptions options) => "J"; + string IPersistableModel.GetFormatFromOptions(ModelReaderWriterOptions options) => "J"; /// Deserializes the model from a raw response. /// The result to deserialize the model from. - internal static ContentFilterResultForResponse FromResponse(PipelineResponse response) + internal static ResponseContentFilterResult FromResponse(PipelineResponse response) { using var document = JsonDocument.Parse(response.Content); - return DeserializeContentFilterResultForResponse(document.RootElement); + return DeserializeResponseContentFilterResult(document.RootElement); } /// Convert into a . diff --git a/sdk/openai/Azure.AI.OpenAI/src/Generated/ContentFilterResultForResponse.cs b/sdk/openai/Azure.AI.OpenAI/src/Generated/ResponseContentFilterResult.cs similarity index 89% rename from sdk/openai/Azure.AI.OpenAI/src/Generated/ContentFilterResultForResponse.cs rename to sdk/openai/Azure.AI.OpenAI/src/Generated/ResponseContentFilterResult.cs index 5228ea56a732..be77b4567b3d 100644 --- a/sdk/openai/Azure.AI.OpenAI/src/Generated/ContentFilterResultForResponse.cs +++ b/sdk/openai/Azure.AI.OpenAI/src/Generated/ResponseContentFilterResult.cs @@ -8,7 +8,7 @@ namespace Azure.AI.OpenAI { /// A content filter result for a single response item produced by a generative AI system. - public partial class ContentFilterResultForResponse + public partial class ResponseContentFilterResult { /// /// Keeps track of any properties unknown to the library. @@ -41,12 +41,12 @@ public partial class ContentFilterResultForResponse /// /// internal IDictionary SerializedAdditionalRawData { get; set; } - /// Initializes a new instance of . - internal ContentFilterResultForResponse() + /// Initializes a new instance of . + internal ResponseContentFilterResult() { } - /// Initializes a new instance of . + /// Initializes a new instance of . /// /// A content filter category for language related to anatomical organs and genitals, romantic relationships, acts /// portrayed in erotic or affectionate terms, pregnancy, physical sexual acts, including those portrayed as an @@ -76,7 +76,7 @@ internal ContentFilterResultForResponse() /// A detection result that describes a match against text protected under copyright or other status. /// A detection result that describes a match against licensed code or other protected source material. /// Keeps track of any properties unknown to the library. - internal ContentFilterResultForResponse(ContentFilterSeverityResult sexual, ContentFilterSeverityResult hate, ContentFilterSeverityResult violence, ContentFilterSeverityResult selfHarm, ContentFilterDetectionResult profanity, ContentFilterBlocklistResult customBlocklists, InternalAzureContentFilterResultForPromptContentFilterResultsError error, ContentFilterDetectionResult protectedMaterialText, ContentFilterProtectedMaterialResult protectedMaterialCode, IDictionary serializedAdditionalRawData) + internal ResponseContentFilterResult(ContentFilterSeverityResult sexual, ContentFilterSeverityResult hate, ContentFilterSeverityResult violence, ContentFilterSeverityResult selfHarm, ContentFilterDetectionResult profanity, ContentFilterBlocklistResult customBlocklists, InternalAzureContentFilterResultForPromptContentFilterResultsError error, ContentFilterDetectionResult protectedMaterialText, ContentFilterProtectedMaterialResult protectedMaterialCode, IDictionary serializedAdditionalRawData) { Sexual = sexual; Hate = hate; diff --git a/sdk/openai/Azure.AI.OpenAI/src/Generated/ImageContentFilterResultForResponse.Serialization.cs b/sdk/openai/Azure.AI.OpenAI/src/Generated/ResponseImageContentFilterResult.Serialization.cs similarity index 72% rename from sdk/openai/Azure.AI.OpenAI/src/Generated/ImageContentFilterResultForResponse.Serialization.cs rename to sdk/openai/Azure.AI.OpenAI/src/Generated/ResponseImageContentFilterResult.Serialization.cs index d666cf634494..ea977b08966e 100644 --- a/sdk/openai/Azure.AI.OpenAI/src/Generated/ImageContentFilterResultForResponse.Serialization.cs +++ b/sdk/openai/Azure.AI.OpenAI/src/Generated/ResponseImageContentFilterResult.Serialization.cs @@ -10,14 +10,14 @@ namespace Azure.AI.OpenAI { - public partial class ImageContentFilterResultForResponse : IJsonModel + public partial class ResponseImageContentFilterResult : IJsonModel { - void IJsonModel.Write(Utf8JsonWriter writer, ModelReaderWriterOptions options) + void IJsonModel.Write(Utf8JsonWriter writer, ModelReaderWriterOptions options) { - var format = options.Format == "W" ? ((IPersistableModel)this).GetFormatFromOptions(options) : options.Format; + var format = options.Format == "W" ? ((IPersistableModel)this).GetFormatFromOptions(options) : options.Format; if (format != "J") { - throw new FormatException($"The model {nameof(ImageContentFilterResultForResponse)} does not support writing '{format}' format."); + throw new FormatException($"The model {nameof(ResponseImageContentFilterResult)} does not support writing '{format}' format."); } writer.WriteStartObject(); @@ -63,19 +63,19 @@ void IJsonModel.Write(Utf8JsonWriter writer writer.WriteEndObject(); } - ImageContentFilterResultForResponse IJsonModel.Create(ref Utf8JsonReader reader, ModelReaderWriterOptions options) + ResponseImageContentFilterResult IJsonModel.Create(ref Utf8JsonReader reader, ModelReaderWriterOptions options) { - var format = options.Format == "W" ? ((IPersistableModel)this).GetFormatFromOptions(options) : options.Format; + var format = options.Format == "W" ? ((IPersistableModel)this).GetFormatFromOptions(options) : options.Format; if (format != "J") { - throw new FormatException($"The model {nameof(ImageContentFilterResultForResponse)} does not support reading '{format}' format."); + throw new FormatException($"The model {nameof(ResponseImageContentFilterResult)} does not support reading '{format}' format."); } using JsonDocument document = JsonDocument.ParseValue(ref reader); - return DeserializeImageContentFilterResultForResponse(document.RootElement, options); + return DeserializeResponseImageContentFilterResult(document.RootElement, options); } - internal static ImageContentFilterResultForResponse DeserializeImageContentFilterResultForResponse(JsonElement element, ModelReaderWriterOptions options = null) + internal static ResponseImageContentFilterResult DeserializeResponseImageContentFilterResult(JsonElement element, ModelReaderWriterOptions options = null) { options ??= ModelSerializationExtensions.WireOptions; @@ -134,46 +134,46 @@ internal static ImageContentFilterResultForResponse DeserializeImageContentFilte } } serializedAdditionalRawData = rawDataDictionary; - return new ImageContentFilterResultForResponse(sexual, violence, hate, selfHarm, serializedAdditionalRawData); + return new ResponseImageContentFilterResult(sexual, violence, hate, selfHarm, serializedAdditionalRawData); } - BinaryData IPersistableModel.Write(ModelReaderWriterOptions options) + BinaryData IPersistableModel.Write(ModelReaderWriterOptions options) { - var format = options.Format == "W" ? ((IPersistableModel)this).GetFormatFromOptions(options) : options.Format; + var format = options.Format == "W" ? ((IPersistableModel)this).GetFormatFromOptions(options) : options.Format; switch (format) { case "J": return ModelReaderWriter.Write(this, options); default: - throw new FormatException($"The model {nameof(ImageContentFilterResultForResponse)} does not support writing '{options.Format}' format."); + throw new FormatException($"The model {nameof(ResponseImageContentFilterResult)} does not support writing '{options.Format}' format."); } } - ImageContentFilterResultForResponse IPersistableModel.Create(BinaryData data, ModelReaderWriterOptions options) + ResponseImageContentFilterResult IPersistableModel.Create(BinaryData data, ModelReaderWriterOptions options) { - var format = options.Format == "W" ? ((IPersistableModel)this).GetFormatFromOptions(options) : options.Format; + var format = options.Format == "W" ? ((IPersistableModel)this).GetFormatFromOptions(options) : options.Format; switch (format) { case "J": { using JsonDocument document = JsonDocument.Parse(data); - return DeserializeImageContentFilterResultForResponse(document.RootElement, options); + return DeserializeResponseImageContentFilterResult(document.RootElement, options); } default: - throw new FormatException($"The model {nameof(ImageContentFilterResultForResponse)} does not support reading '{options.Format}' format."); + throw new FormatException($"The model {nameof(ResponseImageContentFilterResult)} does not support reading '{options.Format}' format."); } } - string IPersistableModel.GetFormatFromOptions(ModelReaderWriterOptions options) => "J"; + string IPersistableModel.GetFormatFromOptions(ModelReaderWriterOptions options) => "J"; /// Deserializes the model from a raw response. /// The result to deserialize the model from. - internal static ImageContentFilterResultForResponse FromResponse(PipelineResponse response) + internal static ResponseImageContentFilterResult FromResponse(PipelineResponse response) { using var document = JsonDocument.Parse(response.Content); - return DeserializeImageContentFilterResultForResponse(document.RootElement); + return DeserializeResponseImageContentFilterResult(document.RootElement); } /// Convert into a . diff --git a/sdk/openai/Azure.AI.OpenAI/src/Generated/ImageContentFilterResultForResponse.cs b/sdk/openai/Azure.AI.OpenAI/src/Generated/ResponseImageContentFilterResult.cs similarity index 89% rename from sdk/openai/Azure.AI.OpenAI/src/Generated/ImageContentFilterResultForResponse.cs rename to sdk/openai/Azure.AI.OpenAI/src/Generated/ResponseImageContentFilterResult.cs index ed4b17e85436..2a5b21055925 100644 --- a/sdk/openai/Azure.AI.OpenAI/src/Generated/ImageContentFilterResultForResponse.cs +++ b/sdk/openai/Azure.AI.OpenAI/src/Generated/ResponseImageContentFilterResult.cs @@ -8,7 +8,7 @@ namespace Azure.AI.OpenAI { /// A content filter result for an image generation operation's output response content. - public partial class ImageContentFilterResultForResponse + public partial class ResponseImageContentFilterResult { /// /// Keeps track of any properties unknown to the library. @@ -41,12 +41,12 @@ public partial class ImageContentFilterResultForResponse /// /// internal IDictionary SerializedAdditionalRawData { get; set; } - /// Initializes a new instance of . - internal ImageContentFilterResultForResponse() + /// Initializes a new instance of . + internal ResponseImageContentFilterResult() { } - /// Initializes a new instance of . + /// Initializes a new instance of . /// /// A content filter category for language related to anatomical organs and genitals, romantic relationships, acts /// portrayed in erotic or affectionate terms, pregnancy, physical sexual acts, including those portrayed as an @@ -68,7 +68,7 @@ internal ImageContentFilterResultForResponse() /// damage one's body or kill oneself. /// /// Keeps track of any properties unknown to the library. - internal ImageContentFilterResultForResponse(ContentFilterSeverityResult sexual, ContentFilterSeverityResult violence, ContentFilterSeverityResult hate, ContentFilterSeverityResult selfHarm, IDictionary serializedAdditionalRawData) + internal ResponseImageContentFilterResult(ContentFilterSeverityResult sexual, ContentFilterSeverityResult violence, ContentFilterSeverityResult hate, ContentFilterSeverityResult selfHarm, IDictionary serializedAdditionalRawData) { Sexual = sexual; Violence = violence; diff --git a/sdk/openai/Azure.AI.OpenAI/tests/Assets/playback_test_config.json b/sdk/openai/Azure.AI.OpenAI/tests/Assets/playback_test_config.json index d55e5d96ef6a..6c1e7cf25306 100644 --- a/sdk/openai/Azure.AI.OpenAI/tests/Assets/playback_test_config.json +++ b/sdk/openai/Azure.AI.OpenAI/tests/Assets/playback_test_config.json @@ -6,9 +6,22 @@ "resource_group": "Sanitized", "subscription_id": "Sanitized" }, + "assistant": { + "deployment": "gpt-4o-mini" + }, "audio": { "deployment": "whisper" }, + "chat": { + "endpoint": "https://Sanitized.openai.azure.com/", + "key": "Sanitized", + "deployment": "gpt-4o-0806" + }, + "chat_with_async_filter": { + "endpoint": "https://Sanitized.openai.azure.com/", + "key": "Sanitized", + "deployment": "gpt-4o-mini-async-block-banana" + }, "embedding": { "deployment": "text-embedding-ada-002" }, @@ -27,12 +40,14 @@ "search": { "endpoint": "https://Sanitized.search.windows.net/", "key": "Sanitized", - "index": "openaiwikisearchindex" + "index": "openai-readmes-index" }, "tts": { "deployment": "tts" }, "vision": { - "deployment": "gpt-4-vision-preview" + "endpoint": "https://Sanitized.openai.azure.com/", + "key": "Sanitized", + "deployment": "gpt-4o-mini" } } \ No newline at end of file diff --git a/sdk/openai/Azure.AI.OpenAI/tests/AssistantTests.cs b/sdk/openai/Azure.AI.OpenAI/tests/AssistantTests.cs index 67b4c354f303..4a3736697688 100644 --- a/sdk/openai/Azure.AI.OpenAI/tests/AssistantTests.cs +++ b/sdk/openai/Azure.AI.OpenAI/tests/AssistantTests.cs @@ -59,8 +59,9 @@ public async Task BasicAssistantOperationsWork() Name = "test assistant name", }); Assert.That(assistant.Name, Is.EqualTo("test assistant name")); - bool deleted = await client.DeleteAssistantAsync(assistant.Id); - Assert.That(deleted, Is.True); + AssistantDeletionResult deletionResult = await client.DeleteAssistantAsync(assistant.Id); + Assert.That(deletionResult.AssistantId, Is.EqualTo(assistant.Id)); + Assert.That(deletionResult.Deleted, Is.True); assistant = await client.CreateAssistantAsync(modelName, new AssistantCreationOptions() { Metadata = @@ -80,8 +81,8 @@ public async Task BasicAssistantOperationsWork() }, }); Assert.That(modifiedAssistant.Id, Is.EqualTo(assistant.Id)); - AsyncPageCollection recentAssistants = client.GetAssistantsAsync(); - Assistant firstAssistant = await recentAssistants.GetAllValuesAsync().FirstOrDefaultAsync(); + AsyncCollectionResult recentAssistants = client.GetAssistantsAsync(); + Assistant firstAssistant = await recentAssistants.FirstOrDefaultAsync(); Assert.That(firstAssistant, Is.Not.Null); Assert.That(firstAssistant.Metadata.TryGetValue("testkey", out string newMetadataValue) && newMetadataValue == "goodbye!"); } @@ -93,8 +94,9 @@ public async Task BasicThreadOperationsWork() AssistantThread thread = await client.CreateThreadAsync(); Validate(thread); Assert.That(thread.CreatedAt, Is.GreaterThan(s_2024)); - bool deleted = await client.DeleteThreadAsync(thread.Id); - Assert.That(deleted, Is.True); + ThreadDeletionResult deletionResult = await client.DeleteThreadAsync(thread.Id); + Assert.That(deletionResult.ThreadId, Is.EqualTo(thread.Id)); + Assert.That(deletionResult.Deleted, Is.True); ThreadCreationOptions options = new() { @@ -118,33 +120,55 @@ public async Task BasicThreadOperationsWork() Assert.That(thread.Metadata.TryGetValue("threadMetadata", out threadMetadataValue) && threadMetadataValue == "newThreadMetadataValue"); } + public enum TestResponseFormatKind + { + Default, + Text, + JsonObject, + JsonSchema, + } + [RecordedTest] - public async Task SettingResponseFormatWorks() + [TestCase(TestResponseFormatKind.Default)] + [TestCase(TestResponseFormatKind.Text)] + [TestCase(TestResponseFormatKind.JsonObject)] + //[TestCase(TestResponseFormatKind.JsonSchema)] + public async Task SettingResponseFormatWorks(TestResponseFormatKind responseFormatKind) { AssistantClient client = GetTestClient(); string modelName = client.DeploymentOrThrow(); - Assistant assistant = await client.CreateAssistantAsync(modelName, new() + AssistantResponseFormat selectedResponseFormat = responseFormatKind switch { - ResponseFormat = AssistantResponseFormat.JsonObject, - }); - Validate(assistant); - Assert.That(assistant.ResponseFormat, Is.EqualTo(AssistantResponseFormat.JsonObject)); - assistant = await client.ModifyAssistantAsync(assistant, new() + TestResponseFormatKind.Text => AssistantResponseFormat.Text, + TestResponseFormatKind.JsonObject => AssistantResponseFormat.JsonObject, + TestResponseFormatKind.JsonSchema => AssistantResponseFormat.CreateJsonSchemaFormat( + name: "food_item_with_ingredients", + jsonSchema: s_foodSchemaBytes, + description: "the name of a food item with a list of its ingredients", + strictSchemaEnabled: true), + _ => null, + }; + + AssistantCreationOptions assistantOptions = new() { - ResponseFormat = AssistantResponseFormat.Text, - }); - Assert.That(assistant.ResponseFormat, Is.EqualTo(AssistantResponseFormat.Text)); + ResponseFormat = selectedResponseFormat, + }; + + Assistant assistant = await client.CreateAssistantAsync(modelName, assistantOptions); + Validate(assistant); + Assert.That(assistant.ResponseFormat, Is.EqualTo(selectedResponseFormat ?? AssistantResponseFormat.Auto)); + AssistantThread thread = await client.CreateThreadAsync(); Validate(thread); + ThreadMessage message = await client.CreateMessageAsync(thread.Id, MessageRole.User, ["Write some JSON for me!"]); Validate(message); - ThreadRun run = await client.CreateRunAsync(thread, assistant, new() - { - ResponseFormat = AssistantResponseFormat.JsonObject, - }); + + ThreadRun run = await client.CreateRunAsync(thread, assistant); Validate(run); - Assert.That(run.ResponseFormat, Is.EqualTo(AssistantResponseFormat.JsonObject)); + + Assert.That(run.ResponseFormat, Is.EqualTo(selectedResponseFormat ?? AssistantResponseFormat.Auto)); } [RecordedTest] @@ -164,11 +188,11 @@ public async Task StreamingToolCall() Print(" >>> Beginning call ... "); - ThreadCreationOptions thrdOpt = new() + ThreadCreationOptions thirdOpt = new() { InitialMessages = { new(MessageRole.User, ["What should I wear outside right now?"]), }, }; - AsyncCollectionResult asyncResults = client.CreateThreadAndRunStreamingAsync(assistant, thrdOpt); + AsyncCollectionResult asyncResults = client.CreateThreadAndRunStreamingAsync(assistant, thirdOpt); Print(" >>> Starting enumeration ..."); @@ -225,8 +249,9 @@ public async Task BasicMessageOperationsWork() if (aoaiDeleteBugFixed) { - bool deleted = await client.DeleteMessageAsync(message); - Assert.That(deleted, Is.True); + MessageDeletionResult deletionResult = await client.DeleteMessageAsync(message); + Assert.That(deletionResult.MessageId, Is.EqualTo(message.Id)); + Assert.That(deletionResult.Deleted, Is.True); } message = await client.CreateMessageAsync(thread.Id, MessageRole.User, ["Goodbye, world!"], new MessageCreationOptions() @@ -288,7 +313,7 @@ public async Task ThreadWithInitialMessagesWorks() }; AssistantThread thread = await client.CreateThreadAsync(options); Validate(thread); - List messageList = await client.GetMessagesAsync(thread, new() { Order = ListOrder.OldestFirst }).ToListAsync(); + List messageList = await client.GetMessagesAsync(thread, new() { Order = MessageCollectionOrder.Ascending }).ToListAsync(); Assert.That(messageList.Count, Is.EqualTo(2)); Assert.That(messageList[0].Role, Is.EqualTo(MessageRole.User)); Assert.That(messageList[0].Content?.Count, Is.EqualTo(1)); @@ -399,39 +424,39 @@ public async Task BasicRunStepFunctionalityWorks() }); } + public enum TestStrictSchemaMode + { + Default, + UseStrictToolParameterSchema, + DoNotUseStrictToolParameterSchema + } + [RecordedTest] - public async Task FunctionToolsWork() + [TestCase(TestStrictSchemaMode.Default)] + //[TestCase(TestStrictSchemaMode.UseStrictToolParameterSchema)] + //[TestCase(TestStrictSchemaMode.DoNotUseStrictToolParameterSchema)] + public async Task FunctionToolsWork(TestStrictSchemaMode schemaMode) { AssistantClient client = GetTestClient(); string modelName = client.DeploymentOrThrow(); - Assistant assistant = await client.CreateAssistantAsync(modelName, new AssistantCreationOptions() + + s_getFoodForDayOfWeekTool.StrictParameterSchemaEnabled = schemaMode switch { - Tools = - { - new FunctionToolDefinition() - { - FunctionName = "get_favorite_food_for_day_of_week", - Description = "gets the user's favorite food for a given day of the week, like Tuesday", - Parameters = BinaryData.FromObjectAsJson(new - { - type = "object", - properties = new - { - day_of_week = new - { - type = "string", - description = "a day of the week, like Tuesday or Saturday", - } - } - }), - }, - }, - }); + TestStrictSchemaMode.UseStrictToolParameterSchema => true, + TestStrictSchemaMode.DoNotUseStrictToolParameterSchema => false, + _ => null, + }; + AssistantCreationOptions options = new() + { + Tools = { s_getFoodForDayOfWeekTool } + }; + + Assistant assistant = await client.CreateAssistantAsync(modelName, options); Validate(assistant); Assert.That(assistant.Tools?.Count, Is.EqualTo(1)); FunctionToolDefinition responseToolDefinition = assistant.Tools[0] as FunctionToolDefinition; - Assert.That(responseToolDefinition?.FunctionName, Is.EqualTo("get_favorite_food_for_day_of_week")); + Assert.That(responseToolDefinition?.FunctionName, Is.EqualTo(s_getFoodForDayOfWeekTool.FunctionName)); Assert.That(responseToolDefinition?.Parameters, Is.Not.Null); ThreadRun run = await client.CreateThreadAndRunAsync( @@ -469,7 +494,7 @@ public async Task FunctionToolsWork() r => r.Status.IsTerminal); Assert.That(run.Status, Is.EqualTo(RunStatus.Completed)); - List messages = await client.GetMessagesAsync(run.ThreadId, new() { Order = ListOrder.NewestFirst }) + List messages = await client.GetMessagesAsync(run.ThreadId, new() { Order = MessageCollectionOrder.Descending }) .ToListAsync(); Assert.That(messages.Count, Is.GreaterThan(1)); Assert.That(messages.ElementAt(0).Role, Is.EqualTo(MessageRole.Assistant)); @@ -573,16 +598,12 @@ This file describes the favorite foods of several people. r => r.Status.IsTerminal); Assert.That(run.Status, Is.EqualTo(RunStatus.Completed)); - AsyncPageCollection messages = client.GetMessagesAsync(thread, new() { Order = ListOrder.NewestFirst }); - int numPages = 0; + AsyncCollectionResult messages = client.GetMessagesAsync(thread, new() { Order = MessageCollectionOrder.Descending }); int numThreads = 0; bool hasCake = false; - await foreach (PageResult page in messages) + await foreach (ThreadMessage message in messages) { - numPages++; - foreach (ThreadMessage message in page.Values) - { - numThreads++; + numThreads++; foreach (MessageContent content in message.Content) { Console.WriteLine(content.Text); @@ -593,9 +614,7 @@ This file describes the favorite foods of several people. } } } - } - Assert.That(numPages, Is.GreaterThan(0)); Assert.That(numThreads, Is.GreaterThan(0)); Assert.That(hasCake, Is.True); } @@ -650,4 +669,40 @@ public async Task StreamingRunWorks() } private static readonly DateTimeOffset s_2024 = new(2024, 1, 1, 0, 0, 0, TimeSpan.Zero); + private static FunctionToolDefinition s_getFoodForDayOfWeekTool = new() + { + FunctionName = "get_favorite_food_for_day_of_week", + Description = "gets the user's favorite food for a given day of the week, like Tuesday", + Parameters = BinaryData.FromObjectAsJson(new + { + type = "object", + properties = new + { + day_of_week = new + { + type = "string", + description = "a day of the week, like Tuesday or Saturday", + } + } + }), + }; + private static readonly BinaryData s_foodSchemaBytes = BinaryData.FromString(""" + { + "type": "object", + "properties": { + "name": { + "type": "string", + "description": "a descriptive name for the food" + }, + "ingredients": { + "type": "array", + "items": { + "type": "string" + }, + "description": "recipe ingredients for the food" + } + }, + "additionalProperties": false + } + """); } diff --git a/sdk/openai/Azure.AI.OpenAI/tests/AudioTests.cs b/sdk/openai/Azure.AI.OpenAI/tests/AudioTests.cs index 5312b8083330..edd216204835 100644 --- a/sdk/openai/Azure.AI.OpenAI/tests/AudioTests.cs +++ b/sdk/openai/Azure.AI.OpenAI/tests/AudioTests.cs @@ -82,8 +82,8 @@ public async Task TranscriptionWorksWithFormat(AudioTranscriptionFormat? format) TranscribedSegment firstSegment = transcription.Segments[0]; Assert.That(firstSegment, Is.Not.Null); Assert.That(firstSegment.Id, Is.EqualTo(0)); - Assert.That(firstSegment.Start, Is.GreaterThanOrEqualTo(TimeSpan.FromSeconds(0))); - Assert.That(firstSegment.End, Is.GreaterThan(firstSegment.Start)); + Assert.That(firstSegment.StartTime, Is.GreaterThanOrEqualTo(TimeSpan.FromSeconds(0))); + Assert.That(firstSegment.EndTime, Is.GreaterThan(firstSegment.StartTime)); Assert.That(firstSegment.Text, Is.Not.Null.Or.Empty); } } @@ -159,8 +159,8 @@ public async Task TranslationWorksWithFormat(AudioTranslationFormat? format) TranscribedSegment firstSegment = translation.Segments[0]; Assert.That(firstSegment, Is.Not.Null); Assert.That(firstSegment.Id, Is.EqualTo(0)); - Assert.That(firstSegment.Start, Is.GreaterThanOrEqualTo(TimeSpan.FromSeconds(0))); - Assert.That(firstSegment.End, Is.GreaterThan(firstSegment.Start)); + Assert.That(firstSegment.StartTime, Is.GreaterThanOrEqualTo(TimeSpan.FromSeconds(0))); + Assert.That(firstSegment.EndTime, Is.GreaterThan(firstSegment.StartTime)); Assert.That(firstSegment.Text, Is.Not.Null.Or.Empty); } } diff --git a/sdk/openai/Azure.AI.OpenAI/tests/BatchTests.cs b/sdk/openai/Azure.AI.OpenAI/tests/BatchTests.cs index 357c022d1c1e..a73d054faced 100644 --- a/sdk/openai/Azure.AI.OpenAI/tests/BatchTests.cs +++ b/sdk/openai/Azure.AI.OpenAI/tests/BatchTests.cs @@ -157,7 +157,7 @@ public async Task UploadBatchFileAsync() } using MemoryStream stream = new MemoryStream(); - JsonHelpers.Serialize(stream, _operations, JsonOptions.OpenAIJsonOptions); + JsonSerializer.Serialize(stream, _operations, JsonOptions.OpenAIJsonOptions); stream.Seek(0, SeekOrigin.Begin); var data = BinaryData.FromStream(stream); diff --git a/sdk/openai/Azure.AI.OpenAI/tests/ChatTests.Functions.cs b/sdk/openai/Azure.AI.OpenAI/tests/ChatTests.Functions.cs index ebe881c6acef..b7c198218f30 100644 --- a/sdk/openai/Azure.AI.OpenAI/tests/ChatTests.Functions.cs +++ b/sdk/openai/Azure.AI.OpenAI/tests/ChatTests.Functions.cs @@ -8,6 +8,7 @@ using System.Text; using System.Text.Json; using System.Threading.Tasks; +using Azure.AI.OpenAI.Chat; using OpenAI.Chat; using OpenAI.TestFramework; @@ -16,10 +17,9 @@ namespace Azure.AI.OpenAI.Tests; public partial class ChatTests { [Obsolete] - private static readonly ChatFunction FUNCTION_TEMPERATURE = new( - "get_future_temperature", - "requests the anticipated future temperature at a provided location to help inform advice about topics like choice of attire", - BinaryData.FromString( + private static readonly ChatFunction FUNCTION_TEMPERATURE = new("get_future_temperature") { + FunctionDescription = "requests the anticipated future temperature at a provided location to help inform advice about topics like choice of attire", + FunctionParameters = BinaryData.FromString( """ { "type": "object", @@ -34,7 +34,7 @@ public partial class ChatTests } } } - """)); + """)}; public enum FunctionCallTestType { @@ -67,7 +67,7 @@ public async Task SimpleFunctionCallWorks(FunctionCallTestType functionCallType) _ => throw new NotImplementedException(), }, Functions = { FUNCTION_TEMPERATURE }, - MaxTokens = 512, + MaxOutputTokenCount = 512, }; ClientResult response = await client.CompleteChatAsync(messages, requestOptions); @@ -77,7 +77,7 @@ public async Task SimpleFunctionCallWorks(FunctionCallTestType functionCallType) Assert.IsNotNull(completion); Assert.That(completion.Id, Is.Not.Null.Or.Empty); - ContentFilterResultForPrompt filter = completion.GetContentFilterResultForPrompt(); + RequestContentFilterResult filter = completion.GetRequestContentFilterResult(); Assert.IsNotNull(filter); Assert.That(filter.SelfHarm, Is.Not.Null); Assert.That(filter.SelfHarm.Filtered, Is.False); @@ -131,14 +131,14 @@ public async Task SimpleFunctionCallWorks(FunctionCallTestType functionCallType) requestOptions = new() { Functions = { FUNCTION_TEMPERATURE }, - MaxTokens = requestOptions.MaxTokens, + MaxOutputTokenCount = 512, }; completion = await client.CompleteChatAsync(messages, requestOptions); Assert.That(completion, Is.Not.Null); Assert.That(completion.FinishReason, Is.EqualTo(ChatFinishReason.Stop)); - ContentFilterResultForResponse responseFilter = completion.GetContentFilterResultForResponse(); + ResponseContentFilterResult responseFilter = completion.GetResponseContentFilterResult(); Assert.That(responseFilter, Is.Not.Null); Assert.That(responseFilter.Hate, Is.Not.Null); Assert.That(responseFilter.Hate.Severity, Is.EqualTo(ContentFilterSeverity.Safe)); @@ -180,7 +180,7 @@ public async Task SimpleFunctionCallWorksStreaming(FunctionCallTestType function _ => throw new NotImplementedException(), }, Functions = { FUNCTION_TEMPERATURE }, - MaxTokens = 512, + MaxOutputTokenCount = 512, }; Action validateUpdate = (update) => @@ -205,7 +205,7 @@ public async Task SimpleFunctionCallWorksStreaming(FunctionCallTestType function content.Append(part.Text); } - var promptFilter = update.GetContentFilterResultForPrompt(); + var promptFilter = update.GetRequestContentFilterResult(); if (!foundPromptFilter && promptFilter?.Hate != null) { Assert.That(promptFilter.Hate.Filtered, Is.False); @@ -213,7 +213,7 @@ public async Task SimpleFunctionCallWorksStreaming(FunctionCallTestType function foundPromptFilter = true; } - var responseFilter = update.GetContentFilterResultForResponse(); + var responseFilter = update.GetResponseContentFilterResult(); if (!foundResponseFilter && responseFilter?.Hate != null) { Assert.That(responseFilter.Hate.Filtered, Is.False); @@ -240,7 +240,7 @@ public async Task SimpleFunctionCallWorksStreaming(FunctionCallTestType function Assert.That(parsedArgs.LocationName, Is.Not.Null.Or.Empty); Assert.That(parsedArgs.Date, Is.Not.Null.Or.Empty); - // TODO FIXME: There isn't a clear or obvious way to pass the assitant function message back to the service, and the constructors that allow + // TODO FIXME: There isn't a clear or obvious way to pass the assistant function message back to the service, and the constructors that allow // us manual control are internal. So let's use JSON. var converted = ModelReaderWriter.Read(BinaryData.FromString(JsonSerializer.Serialize(new { name = functionName, arguments = functionArgs.ToString() }))); messages.Add(new AssistantChatMessage(converted)); @@ -253,7 +253,7 @@ public async Task SimpleFunctionCallWorksStreaming(FunctionCallTestType function requestOptions = new() { Functions = { FUNCTION_TEMPERATURE }, - MaxTokens = requestOptions.MaxTokens, + MaxOutputTokenCount = requestOptions.MaxOutputTokenCount, }; content.Clear(); diff --git a/sdk/openai/Azure.AI.OpenAI/tests/ChatTests.Tools.cs b/sdk/openai/Azure.AI.OpenAI/tests/ChatTests.Tools.cs index 77160c89a626..3ea973957870 100644 --- a/sdk/openai/Azure.AI.OpenAI/tests/ChatTests.Tools.cs +++ b/sdk/openai/Azure.AI.OpenAI/tests/ChatTests.Tools.cs @@ -7,6 +7,8 @@ using System.Text; using System.Text.Json; using System.Threading.Tasks; +using Azure.AI.OpenAI.Chat; +using Azure.AI.OpenAI.Images; using OpenAI.Chat; using OpenAI.TestFramework; @@ -72,14 +74,14 @@ public async Task SimpleToolWorks(ToolChoiceTestType toolChoice) { ToolChoice = toolChoice switch { - ToolChoiceTestType.None => ChatToolChoice.None, - ToolChoiceTestType.Auto => ChatToolChoice.Auto, - ToolChoiceTestType.Tool => new ChatToolChoice(TOOL_TEMPERATURE), - ToolChoiceTestType.Required => ChatToolChoice.Required, + ToolChoiceTestType.None => ChatToolChoice.CreateNoneChoice(), + ToolChoiceTestType.Auto => ChatToolChoice.CreateAutoChoice(), + ToolChoiceTestType.Tool => ChatToolChoice.CreateFunctionChoice(TOOL_TEMPERATURE.FunctionName), + ToolChoiceTestType.Required => ChatToolChoice.CreateRequiredChoice(), _ => throw new NotImplementedException(), }, Tools = { TOOL_TEMPERATURE }, - MaxTokens = 512, + MaxOutputTokenCount = 512, }; ClientResult response = await client.CompleteChatAsync(messages, requestOptions); @@ -89,7 +91,7 @@ public async Task SimpleToolWorks(ToolChoiceTestType toolChoice) Assert.IsNotNull(completion); Assert.That(completion.Id, Is.Not.Null.Or.Empty); - ContentFilterResultForPrompt filter = completion.GetContentFilterResultForPrompt(); + RequestContentFilterResult filter = completion.GetRequestContentFilterResult(); Assert.IsNotNull(filter); Assert.That(filter.SelfHarm, Is.Not.Null); Assert.That(filter.SelfHarm.Filtered, Is.False); @@ -147,20 +149,20 @@ public async Task SimpleToolWorks(ToolChoiceTestType toolChoice) requestOptions = new() { Tools = { TOOL_TEMPERATURE }, - MaxTokens = requestOptions.MaxTokens + MaxOutputTokenCount = requestOptions.MaxOutputTokenCount }; completion = await client.CompleteChatAsync(messages, requestOptions); Assert.That(completion, Is.Not.Null); Assert.That(completion.FinishReason, Is.EqualTo(ChatFinishReason.Stop)); - ContentFilterResultForPrompt promptFilter = completion.GetContentFilterResultForPrompt(); + RequestContentFilterResult promptFilter = completion.GetRequestContentFilterResult(); Assert.That(promptFilter, Is.Not.Null); Assert.That(promptFilter.Hate, Is.Not.Null); Assert.That(promptFilter.Hate.Severity, Is.EqualTo(ContentFilterSeverity.Safe)); Assert.That(promptFilter.Hate.Filtered, Is.False); - ContentFilterResultForResponse responseFilter = completion.GetContentFilterResultForResponse(); + ResponseContentFilterResult responseFilter = completion.GetResponseContentFilterResult(); Assert.That(responseFilter, Is.Not.Null); Assert.That(responseFilter.Hate, Is.Not.Null); Assert.That(responseFilter.Hate.Severity, Is.EqualTo(ContentFilterSeverity.Safe)); @@ -176,7 +178,7 @@ public async Task SimpleToolWorks(ToolChoiceTestType toolChoice) [TestCase(ToolChoiceTestType.None)] [TestCase(ToolChoiceTestType.Auto)] [TestCase(ToolChoiceTestType.Tool)] - [TestCase(ToolChoiceTestType.Required, Ignore = "This seems to be considered invalid")] + [TestCase(ToolChoiceTestType.Required)] public async Task SimpleToolWorksStreaming(ToolChoiceTestType toolChoice) { StringBuilder content = new(); @@ -197,14 +199,14 @@ public async Task SimpleToolWorksStreaming(ToolChoiceTestType toolChoice) { ToolChoice = toolChoice switch { - ToolChoiceTestType.None => ChatToolChoice.None, - ToolChoiceTestType.Auto => ChatToolChoice.Auto, - ToolChoiceTestType.Tool => new ChatToolChoice(TOOL_TEMPERATURE), - ToolChoiceTestType.Required => ChatToolChoice.Required, + ToolChoiceTestType.None => ChatToolChoice.CreateNoneChoice(), + ToolChoiceTestType.Auto => ChatToolChoice.CreateAutoChoice(), + ToolChoiceTestType.Tool => ChatToolChoice.CreateFunctionChoice(TOOL_TEMPERATURE.FunctionName), + ToolChoiceTestType.Required => ChatToolChoice.CreateRequiredChoice(), _ => throw new NotImplementedException(), }, Tools = { TOOL_TEMPERATURE }, - MaxTokens = 512, + MaxOutputTokenCount = 512, }; Action validateUpdate = (update) => @@ -237,7 +239,7 @@ public async Task SimpleToolWorksStreaming(ToolChoiceTestType toolChoice) content.Append(part.Text); } - var promptFilter = update.GetContentFilterResultForPrompt(); + var promptFilter = update.GetRequestContentFilterResult(); if (!foundPromptFilter && promptFilter?.Hate != null) { Assert.That(promptFilter.Hate.Filtered, Is.False); @@ -245,7 +247,7 @@ public async Task SimpleToolWorksStreaming(ToolChoiceTestType toolChoice) foundPromptFilter = true; } - var responseFilter = update.GetContentFilterResultForResponse(); + var responseFilter = update.GetResponseContentFilterResult(); if (!foundResponseFilter && responseFilter?.Hate != null) { Assert.That(responseFilter.Hate.Filtered, Is.False); @@ -296,7 +298,7 @@ public async Task SimpleToolWorksStreaming(ToolChoiceTestType toolChoice) requestOptions = new() { Tools = { TOOL_TEMPERATURE }, - MaxTokens = requestOptions.MaxTokens + MaxOutputTokenCount = requestOptions.MaxOutputTokenCount }; content.Clear(); diff --git a/sdk/openai/Azure.AI.OpenAI/tests/ChatTests.Vision.cs b/sdk/openai/Azure.AI.OpenAI/tests/ChatTests.Vision.cs index 85399aac41ca..86bde5605ab7 100644 --- a/sdk/openai/Azure.AI.OpenAI/tests/ChatTests.Vision.cs +++ b/sdk/openai/Azure.AI.OpenAI/tests/ChatTests.Vision.cs @@ -6,6 +6,7 @@ using System.IO; using System.Text; using System.Threading.Tasks; +using Azure.AI.OpenAI.Chat; using OpenAI.Chat; using OpenAI.TestFramework; @@ -24,27 +25,27 @@ public async Task ChatWithImages(bool useUri) ChatMessageContentPart imagePart; if (useUri) { - imagePart = ChatMessageContentPart.CreateImageMessageContentPart( - imageAsset.Url, ImageChatMessageContentPartDetail.Low); + imagePart = ChatMessageContentPart.CreateImagePart( + imageAsset.Url, ChatImageDetailLevel.Low); } else { using var stream = File.OpenRead(imageAsset.RelativePath); var imageData = BinaryData.FromStream(stream); - imagePart = ChatMessageContentPart.CreateImageMessageContentPart( - imageData, imageAsset.MimeType, ImageChatMessageContentPartDetail.Low); + imagePart = ChatMessageContentPart.CreateImagePart( + imageData, imageAsset.MimeType, ChatImageDetailLevel.Low); } ChatMessage[] messages = [ new SystemChatMessage("You are a helpful assistant that helps describe images."), - new UserChatMessage(imagePart, ChatMessageContentPart.CreateTextMessageContentPart("describe this image")) + new UserChatMessage(imagePart, ChatMessageContentPart.CreateTextPart("describe this image")) ]; ChatCompletionOptions options = new() { - MaxTokens = 2048, + MaxOutputTokenCount = 2048, }; var response = await client.CompleteChatAsync(messages, options); @@ -55,9 +56,9 @@ public async Task ChatWithImages(bool useUri) Assert.That(response.Value.FinishReason, Is.EqualTo(ChatFinishReason.Stop)); Assert.That(response.Value.Role, Is.EqualTo(ChatMessageRole.Assistant)); Assert.That(response.Value.Usage, Is.Not.Null); - Assert.That(response.Value.Usage.InputTokens, Is.GreaterThan(10)); - Assert.That(response.Value.Usage.OutputTokens, Is.GreaterThan(10)); - Assert.That(response.Value.Usage.TotalTokens, Is.GreaterThan(20)); + Assert.That(response.Value.Usage.InputTokenCount, Is.GreaterThan(10)); + Assert.That(response.Value.Usage.OutputTokenCount, Is.GreaterThan(10)); + Assert.That(response.Value.Usage.TotalTokenCount, Is.GreaterThan(20)); Assert.That(response.Value.Content, Has.Count.EqualTo(1)); ChatMessageContentPart choice = response.Value.Content[0]; @@ -66,13 +67,13 @@ public async Task ChatWithImages(bool useUri) Assert.That(choice.Text.ToLowerInvariant(), Does.Contain("dog").Or.Contain("cat")); // TODO FIXME: Some models (e.g. gpt-4o either randomly return prompt filters with some missing entries) - var promptFilter = response.Value.GetContentFilterResultForPrompt(); + var promptFilter = response.Value.GetRequestContentFilterResult(); Assert.That(promptFilter, Is.Not.Null); //Assert.That(promptFilter.Hate, Is.Not.Null); //Assert.That(promptFilter.Hate.Filtered, Is.False); //Assert.That(promptFilter.Hate.Severity, Is.EqualTo(ContentFilterSeverity.Safe)); - var responseFilter = response.Value.GetContentFilterResultForResponse(); + var responseFilter = response.Value.GetResponseContentFilterResult(); Assert.That(responseFilter, Is.Not.Null); Assert.That(responseFilter.Hate, Is.Not.Null); Assert.That(responseFilter.Hate.Filtered, Is.False); @@ -94,27 +95,27 @@ public async Task ChatWithImagesStreaming(bool useUri) var imageAsset = Assets.DogAndCat; if (useUri) { - imagePart = ChatMessageContentPart.CreateImageMessageContentPart( - imageAsset.Url, ImageChatMessageContentPartDetail.Low); + imagePart = ChatMessageContentPart.CreateImagePart( + imageAsset.Url, ChatImageDetailLevel.Low); } else { using var stream = File.OpenRead(imageAsset.RelativePath); var imageData = BinaryData.FromStream(stream); - imagePart = ChatMessageContentPart.CreateImageMessageContentPart( - imageData, imageAsset.MimeType, ImageChatMessageContentPartDetail.Low); + imagePart = ChatMessageContentPart.CreateImagePart( + imageData, imageAsset.MimeType, ChatImageDetailLevel.Low); } ChatMessage[] messages = [ new SystemChatMessage("You are a helpful assistant that helps describe images."), - new UserChatMessage(imagePart, ChatMessageContentPart.CreateTextMessageContentPart("describe this image")) + new UserChatMessage(imagePart, ChatMessageContentPart.CreateTextPart("describe this image")) ]; ChatCompletionOptions options = new() { - MaxTokens = 2048, + MaxOutputTokenCount = 2048, }; AsyncCollectionResult response = client.CompleteChatStreamingAsync(messages, options); @@ -125,9 +126,9 @@ public async Task ChatWithImagesStreaming(bool useUri) ValidateUpdate(update, content, ref foundPromptFilter, ref foundResponseFilter); } - // TOOD FIXME: gpt-4o models seem to return inconsistent prompt filters to skip this for now + // TODO FIXME: gpt-4o models seem to return inconsistent prompt filters to skip this for now //Assert.That(foundPromptFilter, Is.True); - Assert.That(foundResponseFilter, Is.True); + Assert.That(content, Has.Length.GreaterThan(0)); string c = content.ToString().ToLowerInvariant(); diff --git a/sdk/openai/Azure.AI.OpenAI/tests/ChatTests.cs b/sdk/openai/Azure.AI.OpenAI/tests/ChatTests.cs index 8e376ecb441d..323f5d22d18f 100644 --- a/sdk/openai/Azure.AI.OpenAI/tests/ChatTests.cs +++ b/sdk/openai/Azure.AI.OpenAI/tests/ChatTests.cs @@ -10,6 +10,7 @@ using System.Net.Http; using System.Reflection; using System.Text; +using System.Text.Json; using System.Threading.Tasks; using Azure.AI.OpenAI.Chat; using Azure.AI.OpenAI.Tests.Utils.Config; @@ -78,7 +79,7 @@ public void DataSourceSerializationWorks() }, AllowPartialResult = true, QueryType = DataSourceQueryType.Simple, - OutputContextFlags = DataSourceOutputContextFlags.AllRetrievedDocuments | DataSourceOutputContextFlags.Citations, + OutputContextFlags = DataSourceOutputContexts.AllRetrievedDocuments | DataSourceOutputContexts.Citations, VectorizationSource = DataSourceVectorizer.FromEndpoint( new Uri("https://my-embedding.com"), DataSourceAuthentication.FromApiKey("embedding-api-key")), @@ -158,7 +159,7 @@ public async Task DefaultAzureCredentialWorks() } [RecordedTest] - [Ignore("Delay behavior not emulated by recordings, and needs to be run manually with some time in between iterations due to service throttling behaviour")] + [Ignore("Delay behavior not emulated by recordings, and needs to be run manually with some time in between iterations due to service throttling behavior")] [TestCase("x-ms-retry-after-ms", "1000", 1000)] [TestCase("retry-after-ms", "1400", 1400)] [TestCase("Retry-After", "1", 1000)] @@ -288,9 +289,9 @@ public async Task ChatCompletionWithHistoryAndLogProbabilities() Assert.That(response.Content, Is.Not.Null.Or.Empty); Assert.That(response.Content.Count, Is.EqualTo(1)); Assert.That(response.Usage, Is.Not.Null); - Assert.That(response.Usage.InputTokens, Is.GreaterThan(10)); - Assert.That(response.Usage.OutputTokens, Is.GreaterThan(10)); - Assert.That(response.Usage.TotalTokens, Is.GreaterThan(20)); + Assert.That(response.Usage.InputTokenCount, Is.GreaterThan(10)); + Assert.That(response.Usage.OutputTokenCount, Is.GreaterThan(10)); + Assert.That(response.Usage.TotalTokenCount, Is.GreaterThan(20)); Assert.That(response.ContentTokenLogProbabilities, Is.Not.Null.Or.Empty); foreach (var logProb in response.ContentTokenLogProbabilities) { @@ -305,8 +306,8 @@ public async Task ChatCompletionWithHistoryAndLogProbabilities() Assert.That(content.Text, Does .Contain("Fahrenheit") .Or.Contain("Celsius") - .Or.Contain("°F") - .Or.Contain("°C") + .Or.Contain("�F") + .Or.Contain("�C") .Or.Contain("oven")); } @@ -316,7 +317,7 @@ public async Task ChatCompletionWithTextFormat() ChatClient client = GetTestClient(); ChatCompletionOptions options = new() { - ResponseFormat = ChatResponseFormat.Text + ResponseFormat = ChatResponseFormat.CreateTextFormat(), }; ChatCompletion response = await client.CompleteChatAsync([new UserChatMessage("Give me a random number")], options); @@ -330,16 +331,24 @@ public async Task ChatCompletionContentFilter() { ChatClient client = GetTestClient(); ClientResult chatCompletionResult = await client.CompleteChatAsync([ChatMessage.CreateUserMessage("Hello, world!")]); - Console.WriteLine($"--- RESPONSE ---"); ChatCompletion chatCompletion = chatCompletionResult; - ContentFilterResultForPrompt promptFilterResult = chatCompletion.GetContentFilterResultForPrompt(); + RequestContentFilterResult promptFilterResult = chatCompletion.GetRequestContentFilterResult(); Assert.That(promptFilterResult, Is.Not.Null); Assert.That(promptFilterResult.Sexual?.Filtered, Is.False); Assert.That(promptFilterResult.Sexual?.Severity, Is.EqualTo(ContentFilterSeverity.Safe)); - ContentFilterResultForResponse responseFilterResult = chatCompletion.GetContentFilterResultForResponse(); + ResponseContentFilterResult responseFilterResult = chatCompletion.GetResponseContentFilterResult(); Assert.That(responseFilterResult, Is.Not.Null); Assert.That(responseFilterResult.Hate?.Severity, Is.EqualTo(ContentFilterSeverity.Safe)); - Assert.That(responseFilterResult.ProtectedMaterialCode, Is.Null); + if (responseFilterResult.ProtectedMaterialCode is not null) + { + Assert.That(responseFilterResult.ProtectedMaterialCode.Detected, Is.False); + Assert.That(responseFilterResult.ProtectedMaterialCode.Filtered, Is.False); + } + if (responseFilterResult.ProtectedMaterialText is not null) + { + Assert.That(responseFilterResult.ProtectedMaterialText.Detected, Is.False); + Assert.That(responseFilterResult.ProtectedMaterialText.Filtered, Is.False); + } } [RecordedTest] @@ -386,6 +395,53 @@ [new UserChatMessage("What does the term 'PR complete' mean?")], Assert.That(context.Citations[0].Title, Is.Not.Null.Or.Empty); } + [RecordedTest] + public async Task StructuredOutputsWork() + { + ChatClient client = GetTestClient(); + IEnumerable messages = [ + new UserChatMessage("What's heavier, a pound of feathers or sixteen ounces of steel?") + ]; + ChatCompletionOptions options = new ChatCompletionOptions() + { + ResponseFormat = ChatResponseFormat.CreateJsonSchemaFormat( + "test_schema", + BinaryData.FromString(""" + { + "type": "object", + "properties": { + "answer": { + "type": "string" + }, + "steps": { + "type": "array", + "items": { + "type": "string" + } + } + }, + "required": [ + "answer", + "steps" + ], + "additionalProperties": false + } + """), + "a single final answer with a supporting collection of steps", + jsonSchemaIsStrict: true) + }; + ChatCompletion completion = await client.CompleteChatAsync(messages, options)!; + Assert.That(completion, Is.Not.Null); + Assert.That(completion.Refusal, Is.Null.Or.Empty); + Assert.That(completion.Content?.Count, Is.EqualTo(1)); + JsonDocument contentDocument = null!; + Assert.DoesNotThrow(() => contentDocument = JsonDocument.Parse(completion!.Content![0].Text)); + Assert.IsTrue(contentDocument.RootElement.TryGetProperty("answer", out JsonElement answerProperty)); + Assert.IsTrue(answerProperty.ValueKind == JsonValueKind.String); + Assert.IsTrue(contentDocument.RootElement.TryGetProperty("steps", out JsonElement stepsProperty)); + Assert.IsTrue(stepsProperty.ValueKind == JsonValueKind.Array); + } + #endregion #region Streaming chat completion tests @@ -428,11 +484,11 @@ public async Task ChatCompletionStreaming() ChatMessage[] messages = [ new SystemChatMessage("You are a curmudgeon"), - new UserChatMessage("Hello, assitant!") + new UserChatMessage("Hello, assistant!") ]; ChatCompletionOptions options = new() { - MaxTokens = 512, + MaxOutputTokenCount = 512, IncludeLogProbabilities = true, TopLogProbabilityCount = 1, }; @@ -510,8 +566,60 @@ public async Task SearchExtensionWorksStreaming() Assert.That(contexts[0].Citations[0].Title, Is.Not.Null.Or.Empty); } + [RecordedTest] + public async Task AsyncContentFilterWorksStreaming() + { + // Precondition: the target deployment is configured with an async content filter that includes a + // custom blocklist that will filter variations of the word 'banana.' + + ChatClient client = GetTestClient(TestConfig.GetConfig("chat_with_async_filter")); + + StringBuilder contentBuilder = new(); + + List promptFilterResults = []; + List responseFilterResults = []; + + await foreach (StreamingChatCompletionUpdate chatUpdate + in client.CompleteChatStreamingAsync( + [ + "Hello, assistant! What popular kinds of fruit are yellow and grow on trees?" + ])) + { + foreach (ChatMessageContentPart contentPart in chatUpdate.ContentUpdate) + { + contentBuilder.Append(contentPart.Text); + } + + RequestContentFilterResult promptFilterResult = chatUpdate.GetRequestContentFilterResult(); + ResponseContentFilterResult responseFilterResult = chatUpdate.GetResponseContentFilterResult(); + + if (promptFilterResult is not null) + { + promptFilterResults.Add(promptFilterResult); + } + if (responseFilterResult is not null) + { + responseFilterResults.Add(responseFilterResult); + } + } + + string fullContent = contentBuilder.ToString(); + Assert.That(fullContent.ToLowerInvariant(), Does.Contain("banana")); + + Assert.That(promptFilterResults, Has.Count.GreaterThan(0)); + Assert.That(responseFilterResults, Has.Count.GreaterThan(0)); + + Assert.That(responseFilterResults.Any(filterResult + => filterResult.CustomBlocklists?.BlocklistFilterStatuses? + .TryGetValue("TestBlocklistNoBanana", out bool filtered) == true + && filtered)); + } + #endregion + #region Tests for interim o1 model support regarding new max_completion_tokens + + #endregion #region Helper methods private void ValidateUpdate(StreamingChatCompletionUpdate update, StringBuilder builder, ref bool foundPromptFilter, ref bool foundResponseFilter) @@ -519,7 +627,7 @@ private void ValidateUpdate(StreamingChatCompletionUpdate update, StringBuilder if (update.CreatedAt == UNIX_EPOCH) { // This is the first message that usually contains the service's request content filtering - ContentFilterResultForPrompt promptFilter = update.GetContentFilterResultForPrompt(); + RequestContentFilterResult promptFilter = update.GetRequestContentFilterResult(); if (promptFilter?.SelfHarm != null) { Assert.That(promptFilter.SelfHarm.Filtered, Is.False); @@ -534,9 +642,9 @@ private void ValidateUpdate(StreamingChatCompletionUpdate update, StringBuilder Assert.That(update.FinishReason, Is.Null.Or.EqualTo(ChatFinishReason.Stop)); if (update.Usage != null) { - Assert.That(update.Usage.InputTokens, Is.GreaterThanOrEqualTo(0)); - Assert.That(update.Usage.OutputTokens, Is.GreaterThanOrEqualTo(0)); - Assert.That(update.Usage.TotalTokens, Is.GreaterThanOrEqualTo(0)); + Assert.That(update.Usage.InputTokenCount, Is.GreaterThanOrEqualTo(0)); + Assert.That(update.Usage.OutputTokenCount, Is.GreaterThanOrEqualTo(0)); + Assert.That(update.Usage.TotalTokenCount, Is.GreaterThanOrEqualTo(0)); } Assert.That(update.Model, Is.Not.Null); @@ -560,7 +668,7 @@ private void ValidateUpdate(StreamingChatCompletionUpdate update, StringBuilder if (!foundResponseFilter) { - ContentFilterResultForResponse responseFilter = update.GetContentFilterResultForResponse(); + ResponseContentFilterResult responseFilter = update.GetResponseContentFilterResult(); if (responseFilter?.Violence != null) { Assert.That(responseFilter.Violence.Filtered, Is.False); diff --git a/sdk/openai/Azure.AI.OpenAI/tests/EmbeddingTests.cs b/sdk/openai/Azure.AI.OpenAI/tests/EmbeddingTests.cs index 771d59fbb8f4..49ad6cf7f4ec 100644 --- a/sdk/openai/Azure.AI.OpenAI/tests/EmbeddingTests.cs +++ b/sdk/openai/Azure.AI.OpenAI/tests/EmbeddingTests.cs @@ -22,6 +22,6 @@ public async Task SimpleEmbeddingWithTopLevelClient() { EmbeddingClient embeddingClient = GetTestClient(); ClientResult embeddingResult = await embeddingClient.GenerateEmbeddingAsync("sample text to embed"); - Assert.That(embeddingResult?.Value?.Vector.Length, Is.GreaterThan(0)); + Assert.That(embeddingResult?.Value?.ToFloats().Length, Is.GreaterThan(0)); } } diff --git a/sdk/openai/Azure.AI.OpenAI/tests/FileTests.cs b/sdk/openai/Azure.AI.OpenAI/tests/FileTests.cs index 48b533798392..a22127f8edd4 100644 --- a/sdk/openai/Azure.AI.OpenAI/tests/FileTests.cs +++ b/sdk/openai/Azure.AI.OpenAI/tests/FileTests.cs @@ -26,8 +26,9 @@ public async Task CanUploadAndDeleteFiles() "test_file_delete_me.txt", FileUploadPurpose.Assistants); Validate(file); - bool deleted = await client.DeleteFileAsync(file.Id); - Assert.IsTrue(deleted); + FileDeletionResult deletionResult = await client.DeleteFileAsync(file.Id); + Assert.That(deletionResult.FileId, Is.EqualTo(file.Id)); + Assert.IsTrue(deletionResult.Deleted); } [RecordedTest] diff --git a/sdk/openai/Azure.AI.OpenAI/tests/FineTuningTests.cs b/sdk/openai/Azure.AI.OpenAI/tests/FineTuningTests.cs index b77689edfa30..84c70cb45043 100644 --- a/sdk/openai/Azure.AI.OpenAI/tests/FineTuningTests.cs +++ b/sdk/openai/Azure.AI.OpenAI/tests/FineTuningTests.cs @@ -166,7 +166,7 @@ public async Task CreateAndCancelFineTuning() int maxLoops = 10; do { - result = await client.GetJobEventsAsync(job.ID, null, 10, new()).FirstOrDefaultAsync(); + result = await client.GetJobEventsAsync(job.ID, null, 10, new()).GetRawPagesAsync().FirstOrDefaultAsync(); events = ValidateAndParse>(result); if (events.Data?.Count > 0) @@ -193,7 +193,7 @@ public async Task CreateAndCancelFineTuning() Assert.That(job.Status, Is.EqualTo("cancelled")); } - [RecordedTest] + [RecordedTest(AutomaticRecord = false)] [Category("LongRunning")] // CAUTION: This test can take up 30 *minutes* to run in live mode public async Task CreateAndDeleteFineTuning() { @@ -204,7 +204,9 @@ public async Task CreateAndDeleteFineTuning() // upload training data OpenAIFileInfo uploadedFile = await UploadAndWaitForCompleteOrFail(fileClient, fineTuningFile.RelativePath); +#pragma warning disable CS0618 Assert.That(uploadedFile.Status, Is.EqualTo(OpenAIFileStatus.Processed)); +#pragma warning restore CS0618 // Create the fine tuning job using var requestContent = new FineTuningOptions() @@ -229,7 +231,7 @@ public async Task CreateAndDeleteFineTuning() Assert.True(deleted, "Failed to delete fine tuning model: {0}", job.FineTunedModel); } - [RecordedTest] + [RecordedTest(AutomaticRecord = false)] [Category("LongRunning")] // CAUTION: This test can take around 10 to 15 *minutes* in live mode to run public async Task DeployAndChatWithModel() { @@ -321,6 +323,7 @@ private async Task UploadAndWaitForCompleteOrFail(FileClient fil OpenAIFileInfo uploadedFile = await fileClient.UploadFileAsync(path, FileUploadPurpose.FineTune); Validate(uploadedFile); +#pragma warning disable CS0618 uploadedFile = await WaitUntilReturnLast( uploadedFile, () => fileClient.GetFileAsync(uploadedFile.Id), @@ -328,6 +331,7 @@ private async Task UploadAndWaitForCompleteOrFail(FileClient fil TimeSpan.FromSeconds(5), TimeSpan.FromMinutes(5)) .ConfigureAwait(false); +#pragma warning restore CS0618 return uploadedFile; } @@ -351,18 +355,18 @@ private Task WaitForJobToEnd(FineTuningClient client, FineTuningJ } private IAsyncEnumerable EnumerateJobsAsync(FineTuningClient client) - => EnumerateAsync((after, limit, opt) => client.GetJobsAsync(after, limit, opt)); + => EnumerateAsync(client.GetJobsAsync); private IAsyncEnumerable EnumerateCheckpoints(FineTuningClient client, string jobId) => EnumerateAsync((after, limit, opt) => client.GetJobCheckpointsAsync(jobId, after, limit, opt)); - private async IAsyncEnumerable EnumerateAsync(Func> getAsyncEnumerable) + private async IAsyncEnumerable EnumerateAsync(Func getAsyncEnumerable) where T : FineTuningModelBase { int numPerFetch = 10; RequestOptions reqOptions = new(); - await foreach (ClientResult pageResult in getAsyncEnumerable(null, numPerFetch, reqOptions)) + await foreach (ClientResult pageResult in getAsyncEnumerable(null, numPerFetch, reqOptions).GetRawPagesAsync()) { ListResponse items = ValidateAndParse>(pageResult); if (items.Data?.Count > 0) diff --git a/sdk/openai/Azure.AI.OpenAI/tests/ImageTests.cs b/sdk/openai/Azure.AI.OpenAI/tests/ImageTests.cs index f82f5762ff47..e97480a2a4c1 100644 --- a/sdk/openai/Azure.AI.OpenAI/tests/ImageTests.cs +++ b/sdk/openai/Azure.AI.OpenAI/tests/ImageTests.cs @@ -4,6 +4,7 @@ using System; using System.ClientModel; using System.Threading.Tasks; +using Azure.AI.OpenAI.Images; using OpenAI.Images; using OpenAI.TestFramework; @@ -68,8 +69,8 @@ public async Task CanGetContentFilterResults() Assert.That(image, Is.Not.Null); Assert.That(image.ImageUri, Is.Not.Null); Console.WriteLine($"RESPONSE--\n{imageResult.GetRawResponse().Content}"); - ImageContentFilterResultForPrompt promptResults = image.GetContentFilterResultForPrompt(); - ImageContentFilterResultForResponse responseResults = image.GetContentFilterResultForResponse(); + RequestImageContentFilterResult promptResults = image.GetRequestContentFilterResult(); + ResponseImageContentFilterResult responseResults = image.GetResponseContentFilterResult(); Assert.That(promptResults?.Sexual?.Severity, Is.EqualTo(ContentFilterSeverity.Safe)); Assert.That(responseResults?.Sexual?.Severity, Is.EqualTo(ContentFilterSeverity.Safe)); } diff --git a/sdk/openai/Azure.AI.OpenAI/tests/Models/AzureDeploymentClient.cs b/sdk/openai/Azure.AI.OpenAI/tests/Models/AzureDeploymentClient.cs index 3b51c441d76e..866e176d9526 100644 --- a/sdk/openai/Azure.AI.OpenAI/tests/Models/AzureDeploymentClient.cs +++ b/sdk/openai/Azure.AI.OpenAI/tests/Models/AzureDeploymentClient.cs @@ -162,7 +162,7 @@ private static void ThrowOnFailed(PipelineResponse response) && response.Headers.GetFirstOrDefault("Content-Type")?.StartsWith("application/json") == true) { using Stream errorStream = response.Content.ToStream(); - ErrorInfo? error = JsonHelpers.Deserialize(errorStream, JsonOptions.AzureJsonOptions); + ErrorInfo? error = JsonSerializer.Deserialize(errorStream, JsonOptions.AzureJsonOptions); if (error?.Error != null) { throw new ClientResultException($"[{response.Status} - {error.Error.Code}] {error.Error.Message}", response); @@ -178,7 +178,7 @@ private static T FromJsonContent(PipelineResponse response, CancellationToken ThrowOnFailed(response); using Stream stream = response.Content.ToStream(); - return JsonHelpers.Deserialize(stream, JsonOptions.AzureJsonOptions) + return JsonSerializer.Deserialize(stream, JsonOptions.AzureJsonOptions) ?? throw new InvalidDataException("Service returned a null JSON response body"); } diff --git a/sdk/openai/Azure.AI.OpenAI/tests/Models/BatchOptions.cs b/sdk/openai/Azure.AI.OpenAI/tests/Models/BatchOptions.cs index 40a580370065..cf993794d2c7 100644 --- a/sdk/openai/Azure.AI.OpenAI/tests/Models/BatchOptions.cs +++ b/sdk/openai/Azure.AI.OpenAI/tests/Models/BatchOptions.cs @@ -5,8 +5,8 @@ using System.ClientModel; using System.Collections.Generic; using System.IO; +using System.Text.Json; using Azure.AI.OpenAI.Tests.Utils; -using OpenAI.TestFramework.Utils; namespace Azure.AI.OpenAI.Tests.Models; @@ -20,7 +20,7 @@ public class BatchOptions public BinaryContent ToBinaryContent() { using MemoryStream stream = new MemoryStream(); - JsonHelpers.Serialize(stream, this, JsonOptions.OpenAIJsonOptions); + JsonSerializer.Serialize(stream, this, JsonOptions.OpenAIJsonOptions); stream.Seek(0, SeekOrigin.Begin); var data = BinaryData.FromStream(stream); diff --git a/sdk/openai/Azure.AI.OpenAI/tests/Models/FineTuningOptions.cs b/sdk/openai/Azure.AI.OpenAI/tests/Models/FineTuningOptions.cs index 4c44995f81b6..dbf0875603a2 100644 --- a/sdk/openai/Azure.AI.OpenAI/tests/Models/FineTuningOptions.cs +++ b/sdk/openai/Azure.AI.OpenAI/tests/Models/FineTuningOptions.cs @@ -3,8 +3,8 @@ using System.ClientModel; using System.IO; +using System.Text.Json; using Azure.AI.OpenAI.Tests.Utils; -using OpenAI.TestFramework.Utils; namespace Azure.AI.OpenAI.Tests.Models; @@ -19,7 +19,7 @@ public class FineTuningOptions public BinaryContent ToBinaryContent() { MemoryStream stream = new(); - JsonHelpers.Serialize(stream, this, JsonOptions.OpenAIJsonOptions); + JsonSerializer.Serialize(stream, this, JsonOptions.OpenAIJsonOptions); stream.Seek(0, SeekOrigin.Begin); return BinaryContent.Create(stream); } diff --git a/sdk/openai/Azure.AI.OpenAI/tests/Samples/01_Chat.cs b/sdk/openai/Azure.AI.OpenAI/tests/Samples/01_Chat.cs index 3ad7584e5551..54eaf20432fc 100644 --- a/sdk/openai/Azure.AI.OpenAI/tests/Samples/01_Chat.cs +++ b/sdk/openai/Azure.AI.OpenAI/tests/Samples/01_Chat.cs @@ -27,7 +27,7 @@ public void BasicChat() [ // System messages represent instructions or other guidance about how the assistant should behave new SystemChatMessage("You are a helpful assistant that talks like a pirate."), - // User messages represent user input, whether historical or the most recen tinput + // User messages represent user input, whether historical or the most recent input new UserChatMessage("Hi, can you help me?"), // Assistant messages in a request represent conversation history for responses new AssistantChatMessage("Arrr! Of course, me hearty! What can I do for ye?"), @@ -276,7 +276,9 @@ StringBuilder argumentsBuilder functionArgumentBuildersByIndex[indexToIdPair.Key].ToString())); } - conversationMessages.Add(new AssistantChatMessage(toolCalls, contentBuilder.ToString())); + var assistantChatMessage = new AssistantChatMessage(toolCalls); + assistantChatMessage.Content.Add(ChatMessageContentPart.CreateTextPart(contentBuilder.ToString())); + conversationMessages.Add(assistantChatMessage); // Placeholder: each tool call must be resolved, like in the non-streaming case string GetToolCallOutput(ChatToolCall toolCall) => null; diff --git a/sdk/openai/Azure.AI.OpenAI/tests/Utils/AoaiTestBase.cs b/sdk/openai/Azure.AI.OpenAI/tests/Utils/AoaiTestBase.cs index 70c178dd271c..77f34ed40551 100644 --- a/sdk/openai/Azure.AI.OpenAI/tests/Utils/AoaiTestBase.cs +++ b/sdk/openai/Azure.AI.OpenAI/tests/Utils/AoaiTestBase.cs @@ -52,17 +52,17 @@ public class AoaiTestBase : RecordedClientTestBase where TClient : clas public AzureTestEnvironment TestEnvironment { get; } - protected AoaiTestBase(bool isAsync) : this(isAsync, null) + protected AoaiTestBase(bool isAsync) : this(isAsync, null, null) { } - protected AoaiTestBase(bool isAsync, RecordedTestMode? mode = null) - : base(isAsync, mode) + protected AoaiTestBase(bool isAsync, RecordedTestMode? mode = null, bool? automaticRecord = null) + : base(isAsync, mode, automaticRecord) { - TestConfig = new TestConfig(Mode); + TestConfig = new TestConfig(() => Mode); Assets = new Assets(); TestEnvironment = new AzureTestEnvironment(Mode); - // Remove some of the default sanitizers to customize their behaviour + // Remove some of the default sanitizers to customize their behavior RecordingOptions.SanitizersToRemove.AddRange( [ "AZSDK2003", // Location header (we use a less restrictive sanitizer) @@ -236,6 +236,10 @@ public virtual TExplicitClient GetTestClientFrom(TClient client protected override RecordedTestMode GetDefaultRecordedTestMode() => AzureTestEnvironment.DefaultRecordMode; + /// + protected override bool GetDefaultAutomaticRecordEnabled() + => !IsRunningInCI && AzureTestEnvironment.DefaultAutomaticRecordEnabled; + /// protected override ProxyServiceOptions CreateProxyServiceOptions() => new() @@ -709,7 +713,7 @@ protected virtual TModel ValidateAndParse(ClientResult result, JsonSeria using Stream stream = response.Content.ToStream(); Assert.That(stream, Is.Not.Null); - TModel? model = JsonHelpers.Deserialize(stream, options ?? JsonOptions.OpenAIJsonOptions); + TModel? model = JsonSerializer.Deserialize(stream, options ?? JsonOptions.OpenAIJsonOptions); Assert.That(model, Is.Not.Null); return model!; } diff --git a/sdk/openai/Azure.AI.OpenAI/tests/Utils/AzureTestEnvironment.cs b/sdk/openai/Azure.AI.OpenAI/tests/Utils/AzureTestEnvironment.cs index be87fb307aba..a0321edcce9b 100644 --- a/sdk/openai/Azure.AI.OpenAI/tests/Utils/AzureTestEnvironment.cs +++ b/sdk/openai/Azure.AI.OpenAI/tests/Utils/AzureTestEnvironment.cs @@ -131,7 +131,7 @@ public static RecordedTestMode DefaultRecordMode get { string? modeString = TestContext.Parameters["TestMode"] - ?? Environment.GetEnvironmentVariable("AZURE_TEST_MODE"); + ?? Environment.GetEnvironmentVariable("AZURE_TEST_MODE"); if (Enum.TryParse(modeString, true, out RecordedTestMode mode)) { @@ -142,6 +142,25 @@ public static RecordedTestMode DefaultRecordMode } } + /// + /// Gets whether or not we should automatically record tests. + /// + public static bool DefaultAutomaticRecordEnabled + { + get + { + string? enabledString = TestContext.Parameters["DisableAutoRecording"] + ?? Environment.GetEnvironmentVariable("AZURE_DISABLE_AUTO_RECORDING"); + + if (bool.TryParse(enabledString, out bool enabled)) + { + return !enabled; + } + + return true; + } + } + /// /// Gets an optional value from environment variables. /// diff --git a/sdk/openai/Azure.AI.OpenAI/tests/Utils/Config/JsonConfig.cs b/sdk/openai/Azure.AI.OpenAI/tests/Utils/Config/JsonConfig.cs index e7334b11fe8c..67c0b7accf4a 100644 --- a/sdk/openai/Azure.AI.OpenAI/tests/Utils/Config/JsonConfig.cs +++ b/sdk/openai/Azure.AI.OpenAI/tests/Utils/Config/JsonConfig.cs @@ -5,7 +5,6 @@ using System.Collections.Generic; using System.Text.Json; using System.Text.Json.Serialization; -using OpenAI.TestFramework.Utils; namespace Azure.AI.OpenAI.Tests.Utils.Config; @@ -29,11 +28,7 @@ public class JsonConfig : IConfiguration DictionaryKeyPolicy = JsonOptions.SnakeCaseLower, WriteIndented = true, AllowTrailingCommas = true, -#if NETFRAMEWORK - IgnoreNullValues = true, -#else DefaultIgnoreCondition = JsonIgnoreCondition.WhenWritingNull, -#endif }; /// diff --git a/sdk/openai/Azure.AI.OpenAI/tests/Utils/Config/SanitizedJsonConfig.cs b/sdk/openai/Azure.AI.OpenAI/tests/Utils/Config/SanitizedJsonConfig.cs index 54e111aa7f8c..7c726ca29ca0 100644 --- a/sdk/openai/Azure.AI.OpenAI/tests/Utils/Config/SanitizedJsonConfig.cs +++ b/sdk/openai/Azure.AI.OpenAI/tests/Utils/Config/SanitizedJsonConfig.cs @@ -143,7 +143,7 @@ public virtual void SetValue(string key, TVal? value) else { value = MaskData(key, value); - JsonElement json = JsonHelpers.SerializeToElement(value, JsonConfig.JSON_OPTIONS); + JsonElement json = JsonSerializer.SerializeToElement(value, JsonConfig.JSON_OPTIONS); ExtensionData[key] = json; } } diff --git a/sdk/openai/Azure.AI.OpenAI/tests/Utils/JsonOptions.cs b/sdk/openai/Azure.AI.OpenAI/tests/Utils/JsonOptions.cs index 4489b016922a..29e8d8d548b2 100644 --- a/sdk/openai/Azure.AI.OpenAI/tests/Utils/JsonOptions.cs +++ b/sdk/openai/Azure.AI.OpenAI/tests/Utils/JsonOptions.cs @@ -25,11 +25,7 @@ public static class JsonOptions { PropertyNameCaseInsensitive = true, PropertyNamingPolicy = SnakeCaseLower, -#if NETFRAMEWORK - IgnoreNullValues = true, -#else DefaultIgnoreCondition = System.Text.Json.Serialization.JsonIgnoreCondition.WhenWritingNull, -#endif Converters = { new ModelReaderWriterConverter(), @@ -41,11 +37,7 @@ public static class JsonOptions { PropertyNameCaseInsensitive = true, PropertyNamingPolicy = JsonNamingPolicy.CamelCase, -#if NETFRAMEWORK - IgnoreNullValues = true, -#else DefaultIgnoreCondition = System.Text.Json.Serialization.JsonIgnoreCondition.WhenWritingNull, -#endif }; // Ported over from the source code for newer versions of System.Text.Json diff --git a/sdk/openai/Azure.AI.OpenAI/tests/Utils/TestConfig.cs b/sdk/openai/Azure.AI.OpenAI/tests/Utils/TestConfig.cs index 5b999e1182ec..14aa617a3418 100644 --- a/sdk/openai/Azure.AI.OpenAI/tests/Utils/TestConfig.cs +++ b/sdk/openai/Azure.AI.OpenAI/tests/Utils/TestConfig.cs @@ -18,50 +18,50 @@ internal class TestConfig { private const string AZURE_OPENAI_ENV_KEY_PREFIX = "AZURE_OPENAI"; - private readonly bool _isPlayback; - private readonly IReadOnlyDictionary _jsonConfig; + private readonly Func _getRecordedMode; private SortedDictionary _recordedConfig; + private readonly IReadOnlyDictionary _liveConfig; + private readonly IReadOnlyDictionary _playbackConfig; public virtual string AssetsSubFolder => "Assets"; public virtual string AssetsJson => "test_config.json"; public virtual string PlaybackAssetsJson => $"playback_{AssetsJson}"; - public TestConfig(RecordedTestMode? mode) + protected bool IsPlayback => _getRecordedMode() == RecordedTestMode.Playback; + + // When in playback mode, we always use the playback configuration. This ensures that we run in the same way in CI/CD + // as we do locally. + protected IReadOnlyDictionary CurrentConfig => IsPlayback ? _playbackConfig : _liveConfig; + + public TestConfig(Func getRecordedMode) { - _isPlayback = mode == RecordedTestMode.Playback; + _getRecordedMode = getRecordedMode ?? throw new ArgumentNullException(nameof(getRecordedMode)); _recordedConfig = new(new DefaultFirstStringComparer()); // Load the previous playback configuration and use that to initialize the recorded config string playbackConfigJson = Path.Combine(AssetsSubFolder, PlaybackAssetsJson); - var playbackConfig = ReadJsonConfig(playbackConfigJson); - if (playbackConfig != null) + _playbackConfig = ReadJsonConfig(playbackConfigJson)!; + if (_playbackConfig == null) { - foreach (var kvp in playbackConfig) - { - _recordedConfig.Add(kvp.Key, new SanitizedJsonConfig(kvp.Value)); - } + throw new InvalidOperationException($"The playback config file was not found: {playbackConfigJson}"); } - // When in playback mode, we always use the playback configuration. This ensures that we run in the same way in CI/CD - // as we do locally. - if (_isPlayback) + foreach (var kvp in _playbackConfig) { - _jsonConfig = playbackConfig - ?? throw new InvalidOperationException($"The playback config file was not found: {playbackConfigJson}"); - } - else - { - _jsonConfig = new[] - { - AssetsJson, - Path.Combine(AssetsSubFolder, AssetsJson), - Path.Combine(Environment.GetFolderPath(Environment.SpecialFolder.UserProfile), ".azure", AssetsSubFolder, AssetsJson), - Path.Combine(Environment.GetFolderPath(Environment.SpecialFolder.ApplicationData), ".azure", AssetsSubFolder, AssetsJson), - } - .Select(f => ReadJsonConfig(f)) - .FirstOrDefault(c => c != null) - ?? new Dictionary(); + _recordedConfig.Add(kvp.Key, new SanitizedJsonConfig(kvp.Value)); } + + // Try to load the configuration to use against the real service (e.g. recording or live mode) + _liveConfig = new[] + { + AssetsJson, + Path.Combine(AssetsSubFolder, AssetsJson), + Path.Combine(Environment.GetFolderPath(Environment.SpecialFolder.UserProfile), ".azure", AssetsSubFolder, AssetsJson), + Path.Combine(Environment.GetFolderPath(Environment.SpecialFolder.ApplicationData), ".azure", AssetsSubFolder, AssetsJson), + } + .Select(f => ReadJsonConfig(f)) + .FirstOrDefault(c => c != null) + ?? new Dictionary(); } public virtual IConfiguration? GetConfig() @@ -72,16 +72,16 @@ public TestConfig(RecordedTestMode? mode) // In order to populate each property of the Config object, the search order is as follows: // 1. Getting the specific config for the name in the JSON config file // 2. Getting the value from the default config - // 3. (Not in playback) Getting the value from the AZURE_OPENAI__ environment variable - // 4. (Not in playback) Getting the value from the AZURE_OPENAI_ environment variable + // 3. (Not in playback) Getting the value from the AZURE_OPENAI__ environment variable + // 4. (Not in playback) Getting the value from the AZURE_OPENAI_ environment variable // It will fall through each one if the value is null return new FlattenedConfig( [ - new NamedConfig(_jsonConfig.GetValueOrDefault(name), name), - new NamedConfig(_jsonConfig.GetValueOrDefault(JsonConfig.DEFAULT_CONFIG_NAME), null), - _isPlayback ? null : new EnvironmentValuesConfig(AZURE_OPENAI_ENV_KEY_PREFIX, name), - _isPlayback ? null : new EnvironmentValuesConfig(AZURE_OPENAI_ENV_KEY_PREFIX) + new NamedConfig(CurrentConfig.GetValueOrDefault(name), name), + new NamedConfig(CurrentConfig.GetValueOrDefault(JsonConfig.DEFAULT_CONFIG_NAME), null), + IsPlayback ? null : new EnvironmentValuesConfig(AZURE_OPENAI_ENV_KEY_PREFIX, name), + IsPlayback ? null : new EnvironmentValuesConfig(AZURE_OPENAI_ENV_KEY_PREFIX) ], _recordedConfig); } diff --git a/sdk/openai/Azure.AI.OpenAI/tests/VectorStoreTests.cs b/sdk/openai/Azure.AI.OpenAI/tests/VectorStoreTests.cs index cb6dc8e17ead..95a137cf6012 100644 --- a/sdk/openai/Azure.AI.OpenAI/tests/VectorStoreTests.cs +++ b/sdk/openai/Azure.AI.OpenAI/tests/VectorStoreTests.cs @@ -12,6 +12,7 @@ using Azure.AI.OpenAI.Tests.Utils.Config; using NUnit.Framework; using OpenAI; +using OpenAI.Assistants; using OpenAI.Files; using OpenAI.TestFramework; using OpenAI.VectorStores; @@ -38,8 +39,9 @@ public async Task CanCreateGetAndDeleteVectorStores() VectorStore vectorStore = await client.CreateVectorStoreAsync(); Validate(vectorStore); - bool deleted = await client.DeleteVectorStoreAsync(vectorStore); - Assert.That(deleted, Is.True); + VectorStoreDeletionResult deletionResult = await client.DeleteVectorStoreAsync(vectorStore); + Assert.That(deletionResult.VectorStoreId, Is.EqualTo(vectorStore.Id)); + Assert.That(deletionResult.Deleted, Is.True); IReadOnlyList testFiles = await GetNewTestFilesAsync(client.GetConfigOrThrow(), 5); @@ -81,13 +83,16 @@ public async Task CanCreateGetAndDeleteVectorStores() Assert.That(vectorStore.Metadata?.TryGetValue("test-key", out string metadataValue) == true && metadataValue == "test-value"); }); - deleted = await client.DeleteVectorStoreAsync(vectorStore.Id); - Assert.That(deleted, Is.True); + deletionResult = await client.DeleteVectorStoreAsync(vectorStore.Id); + Assert.That(deletionResult.VectorStoreId, Is.EqualTo(vectorStore.Id)); + Assert.That(deletionResult.Deleted, Is.True); - vectorStore = await client.CreateVectorStoreAsync(new VectorStoreCreationOptions() + var options = new VectorStoreCreationOptions(); + foreach (var file in testFiles) { - FileIds = testFiles.Select(file => file.Id).ToList() - }); + options.FileIds.Add(file.Id); + } + vectorStore = await client.CreateVectorStoreAsync(options); Validate(vectorStore); Assert.Multiple(() => { @@ -110,12 +115,12 @@ public async Task CanEnumerateVectorStores() Assert.That(vectorStore.Name, Is.EqualTo($"Test Vector Store {i}")); } - AsyncPageCollection response = client.GetVectorStoresAsync(new VectorStoreCollectionOptions() { Order = ListOrder.NewestFirst }); + AsyncCollectionResult response = client.GetVectorStoresAsync(new VectorStoreCollectionOptions() { Order = VectorStoreCollectionOrder.Descending }); Assert.That(response, Is.Not.Null); int lastIdSeen = int.MaxValue; int count = 0; - await foreach (VectorStore vectorStore in response.GetAllValuesAsync()) + await foreach (VectorStore vectorStore in response) { Assert.That(vectorStore.Id, Is.Not.Null); if (vectorStore.Name?.StartsWith("Test Vector Store ") == true) @@ -158,15 +163,16 @@ public async Task CanAssociateFiles() }); } - bool removed = await client.RemoveFileFromStoreAsync(vectorStore, files[0]); - Assert.True(removed); + FileFromStoreRemovalResult removalResult = await client.RemoveFileFromStoreAsync(vectorStore, files[0]); + Assert.That(removalResult.FileId, Is.EqualTo(files[0].Id)); + Assert.True(removalResult.Removed); // Errata: removals aren't immediately reflected when requesting the list Thread.Sleep(1000); int count = 0; - AsyncPageCollection response = client.GetFileAssociationsAsync(vectorStore); - await foreach (VectorStoreFileAssociation association in response.GetAllValuesAsync()) + AsyncCollectionResult response = client.GetFileAssociationsAsync(vectorStore); + await foreach (VectorStoreFileAssociation association in response) { count++; Assert.That(association.FileId, Is.Not.EqualTo(files[0].Id)); @@ -199,8 +205,8 @@ public async Task CanUseBatchIngestion() b => b.Status != VectorStoreBatchFileJobStatus.InProgress); Assert.That(batchJob.Status, Is.EqualTo(VectorStoreBatchFileJobStatus.Completed)); - AsyncPageCollection response = client.GetFileAssociationsAsync(batchJob); - await foreach (VectorStoreFileAssociation association in response.GetAllValuesAsync()) + AsyncCollectionResult response = client.GetFileAssociationsAsync(batchJob); + await foreach (VectorStoreFileAssociation association in response) { Assert.Multiple(() => { diff --git a/sdk/openai/tools/TestFramework/src/Adapters/SyncToAsyncCollectionResult.cs b/sdk/openai/tools/TestFramework/src/Adapters/SyncToAsyncCollectionResult.cs index 64096eb4af54..6f488e9c1e4a 100644 --- a/sdk/openai/tools/TestFramework/src/Adapters/SyncToAsyncCollectionResult.cs +++ b/sdk/openai/tools/TestFramework/src/Adapters/SyncToAsyncCollectionResult.cs @@ -2,20 +2,19 @@ // Licensed under the MIT License. using System.ClientModel; -using System.Runtime.CompilerServices; +using System.ClientModel.Primitives; using System.Runtime.ExceptionServices; namespace OpenAI.TestFramework.Adapters; /// -/// An adapter to make a look and work like a . This -/// simplifies writing test cases +/// An adapter to make a look and work like a . This +/// simplifies writing test cases. /// /// The type of the items the enumerator returns -public class SyncToAsyncCollectionResult : AsyncCollectionResult +public class SyncToAsyncCollectionResult : AsyncCollectionResult { - private bool _responseSet; - private CollectionResult? _syncCollection; + private CollectionResult? _syncCollection; private Exception? _ex; /// @@ -23,10 +22,9 @@ public class SyncToAsyncCollectionResult : AsyncCollectionResult /// /// The synchronous collection to wrap /// If the collection was null - public SyncToAsyncCollectionResult(CollectionResult syncCollection) + public SyncToAsyncCollectionResult(CollectionResult syncCollection) { _syncCollection = syncCollection ?? throw new ArgumentNullException(nameof(syncCollection)); - TrySetRawResponse(); } /// @@ -37,47 +35,27 @@ public SyncToAsyncCollectionResult(CollectionResult syncCollection) public SyncToAsyncCollectionResult(Exception ex) { _ex = ex ?? throw new ArgumentNullException(nameof(ex)); - _syncCollection = null; } /// - public override IAsyncEnumerator GetAsyncEnumerator(CancellationToken cancellationToken = default) - { - return InnerEnumerable(cancellationToken).GetAsyncEnumerator(); - } - - private async IAsyncEnumerable InnerEnumerable([EnumeratorCancellation] CancellationToken cancellationToken = default) + public override ContinuationToken? GetContinuationToken(ClientResult page) { if (_ex != null) { ExceptionDispatchInfo.Capture(_ex).Throw(); } - var asyncWrapper = new SyncToAsyncEnumerator(_syncCollection?.GetEnumerator()!, cancellationToken); - while (await asyncWrapper.MoveNextAsync().ConfigureAwait(false)) - { - TrySetRawResponse(); - yield return asyncWrapper.Current; - } + return _syncCollection!.GetContinuationToken(page); } - private void TrySetRawResponse() + /// + public override IAsyncEnumerable GetRawPagesAsync() { - if (_responseSet) + if (_ex != null) { - return; + ExceptionDispatchInfo.Capture(_ex).Throw(); } - // Client result doesn't provide virtual methods so we have to manually set it ourselves here - try - { - var raw = _syncCollection?.GetRawResponse(); - if (raw != null) - { - SetRawResponse(raw); - _responseSet = true; - } - } - catch (Exception) { /* dont' care */ } + return new SyncToAsyncEnumerable(_syncCollection!.GetRawPages()); } } diff --git a/sdk/openai/tools/TestFramework/src/Adapters/SyncToAsyncCollectionResultOfT.cs b/sdk/openai/tools/TestFramework/src/Adapters/SyncToAsyncCollectionResultOfT.cs new file mode 100644 index 000000000000..4136df745b41 --- /dev/null +++ b/sdk/openai/tools/TestFramework/src/Adapters/SyncToAsyncCollectionResultOfT.cs @@ -0,0 +1,73 @@ +// Copyright (c) Microsoft Corporation. All rights reserved. +// Licensed under the MIT License. + +using System.ClientModel; +using System.Runtime.ExceptionServices; +using OpenAI.TestFramework.Utils; + +namespace OpenAI.TestFramework.Adapters; + +/// +/// An adapter to make a look and work like a . This +/// simplifies writing test cases +/// +/// The type of the items the enumerator returns +public class SyncToAsyncCollectionResult : AsyncCollectionResult +{ + private CollectionResult? _syncCollection; + private Exception? _ex; + + /// + /// Creates a new instance + /// + /// The synchronous collection to wrap + /// If the collection was null + public SyncToAsyncCollectionResult(CollectionResult syncCollection) + { + _syncCollection = syncCollection ?? throw new ArgumentNullException(nameof(syncCollection)); + } + + /// + /// Creates a new instance. + /// + /// The exception to throw. + /// If the exception was null. + public SyncToAsyncCollectionResult(Exception ex) + { + _ex = ex ?? throw new ArgumentNullException(nameof(ex)); + } + + /// + public override ContinuationToken? GetContinuationToken(ClientResult page) + { + if (_ex != null) + { + ExceptionDispatchInfo.Capture(_ex).Throw(); + } + + return _syncCollection!.GetContinuationToken(page); + } + + /// + public override IAsyncEnumerable GetRawPagesAsync() + { + if (_ex != null) + { + ExceptionDispatchInfo.Capture(_ex).Throw(); + } + + return new SyncToAsyncEnumerable(_syncCollection!.GetRawPages()); + } + + /// + protected override IAsyncEnumerable GetValuesFromPageAsync(ClientResult page) + { + if (_ex != null) + { + ExceptionDispatchInfo.Capture(_ex).Throw(); + } + + var items = NonPublic.FromMethod, ClientResult, IEnumerable>("GetValuesFromPage")(_syncCollection!, page); + return new SyncToAsyncEnumerable(items); + } +} diff --git a/sdk/openai/tools/TestFramework/src/Adapters/SyncToAsyncPageCollection.cs b/sdk/openai/tools/TestFramework/src/Adapters/SyncToAsyncPageCollection.cs deleted file mode 100644 index 89b963137613..000000000000 --- a/sdk/openai/tools/TestFramework/src/Adapters/SyncToAsyncPageCollection.cs +++ /dev/null @@ -1,67 +0,0 @@ -// Copyright (c) Microsoft Corporation. All rights reserved. -// Licensed under the MIT License. - -using System.ClientModel; -using System.Runtime.ExceptionServices; - -namespace OpenAI.TestFramework.Adapters; - -/// -/// An adapter to make a look and work like a . This -/// simplifies writing test cases. -/// -/// The type of the items the enumerator returns. -public class SyncToAsyncPageCollection : AsyncPageCollection -{ - private PageCollection? _syncCollection; - private Exception? _ex; - - /// - /// Creates a new instance. - /// - /// The synchronous collection to wrap. - /// If the collection was null. - public SyncToAsyncPageCollection(PageCollection syncCollection) - { - _syncCollection = syncCollection ?? throw new ArgumentNullException(nameof(syncCollection)); - } - - /// - /// Creates a new instance. - /// - /// The exception to throw. - /// If the exception was null. - public SyncToAsyncPageCollection(Exception ex) - { - _ex = ex ?? throw new ArgumentNullException(nameof(ex)); - _syncCollection = null; - } - - /// - protected override Task> GetCurrentPageAsyncCore() - { - if (_ex != null) - { - return Task.FromException>(_ex); - } - else - { - return Task.FromResult(_syncCollection!.GetCurrentPage()); - } - } - - /// - protected override async IAsyncEnumerator> GetAsyncEnumeratorCore(CancellationToken cancellationToken = default) - { - if (_ex != null) - { - ExceptionDispatchInfo.Capture(_ex).Throw(); - } - - foreach (PageResult page in _syncCollection!) - { - await Task.Delay(0).ConfigureAwait(false); - yield return page; - } - } -} diff --git a/sdk/openai/tools/TestFramework/src/AutoSyncAsync/AsyncToSyncInterceptor.cs b/sdk/openai/tools/TestFramework/src/AutoSyncAsync/AsyncToSyncInterceptor.cs index 08fe268ec8c2..d8038ec44a66 100644 --- a/sdk/openai/tools/TestFramework/src/AutoSyncAsync/AsyncToSyncInterceptor.cs +++ b/sdk/openai/tools/TestFramework/src/AutoSyncAsync/AsyncToSyncInterceptor.cs @@ -2,6 +2,7 @@ // Licensed under the MIT License. using System.ClientModel; +using System.ClientModel.Primitives; using System.Collections.Concurrent; using System.Diagnostics; using System.Reflection; @@ -186,14 +187,14 @@ protected virtual Type ToSyncRetType(Type asyncReturnType) { return genericTypes[0]; } - else if (Ext.IsClosedGenericOf(asyncReturnType, typeof(AsyncPageCollection<>), out genericTypes)) - { - return typeof(PageCollection<>).MakeGenericType(genericTypes); - } else if (Ext.IsClosedGenericOf(asyncReturnType, typeof(AsyncCollectionResult<>), out genericTypes)) { return typeof(CollectionResult<>).MakeGenericType(genericTypes); } + else if (typeof(AsyncCollectionResult).IsAssignableFrom(asyncReturnType)) + { + return typeof(CollectionResult); + } else if (Ext.IsClosedGenericOf(asyncReturnType, typeof(IAsyncEnumerable<>), out genericTypes)) { return typeof(IEnumerable<>).MakeGenericType(genericTypes); @@ -233,16 +234,16 @@ protected virtual Type ToSyncRetType(Type asyncReturnType) typeof(ValueTask<>).MakeGenericType(genericTypes), result); } - else if (Ext.IsClosedGenericOf(asyncReturnType, typeof(AsyncPageCollection<>), out genericTypes)) + else if (Ext.IsClosedGenericOf(asyncReturnType, typeof(AsyncCollectionResult<>), out genericTypes)) { return Activator.CreateInstance( - typeof(SyncToAsyncPageCollection<>).MakeGenericType(genericTypes), + typeof(SyncToAsyncCollectionResult<>).MakeGenericType(genericTypes), result); } - else if (Ext.IsClosedGenericOf(asyncReturnType, typeof(AsyncCollectionResult<>), out genericTypes)) + else if (typeof(AsyncCollectionResult).IsAssignableFrom(asyncReturnType)) { return Activator.CreateInstance( - typeof(SyncToAsyncCollectionResult<>).MakeGenericType(genericTypes), + typeof(SyncToAsyncCollectionResult), result); } else if (Ext.IsClosedGenericOf(asyncReturnType, typeof(IAsyncEnumerable<>), out genericTypes)) @@ -289,16 +290,16 @@ protected virtual Type ToSyncRetType(Type asyncReturnType) typeof(ValueTask<>).MakeGenericType(genericTypes), failedTask); } - else if (Ext.IsClosedGenericOf(asyncReturnType, typeof(AsyncPageCollection<>), out genericTypes)) + else if (Ext.IsClosedGenericOf(asyncReturnType, typeof(AsyncCollectionResult<>), out genericTypes)) { return Activator.CreateInstance( - typeof(SyncToAsyncPageCollection<>).MakeGenericType(genericTypes), + typeof(SyncToAsyncCollectionResult<>).MakeGenericType(genericTypes), ex); } - else if (Ext.IsClosedGenericOf(asyncReturnType, typeof(AsyncCollectionResult<>), out genericTypes)) + else if (typeof(AsyncCollectionResult).IsAssignableFrom(asyncReturnType)) { return Activator.CreateInstance( - typeof(SyncToAsyncCollectionResult<>).MakeGenericType(genericTypes), + typeof(SyncToAsyncCollectionResult), ex); } else if (Ext.IsClosedGenericOf(asyncReturnType, typeof(IAsyncEnumerable<>), out genericTypes)) diff --git a/sdk/openai/tools/TestFramework/src/AutoSyncAsync/AutoSyncAsyncMixIn.cs b/sdk/openai/tools/TestFramework/src/AutoSyncAsync/AutoSyncAsyncMixIn.cs index 538f8fb75d16..4251d02ccc8b 100644 --- a/sdk/openai/tools/TestFramework/src/AutoSyncAsync/AutoSyncAsyncMixIn.cs +++ b/sdk/openai/tools/TestFramework/src/AutoSyncAsync/AutoSyncAsyncMixIn.cs @@ -4,8 +4,9 @@ namespace OpenAI.TestFramework.AutoSyncAsync; /// -/// An implementation of that allows you to get the original back, as well as a place -/// to store an additional context. +/// A helper class for the automatic sync/async testing. This is mixed in with (aka added to) the dynamic proxy +/// that is generated around a client instance. This allows you to a simple way to get the original back, as +/// well as a place to store an additional context. /// public class AutoSyncAsyncMixIn : IAutoSyncAsync { diff --git a/sdk/openai/tools/TestFramework/src/Mocks/MockAsyncCollectionResult.cs b/sdk/openai/tools/TestFramework/src/Mocks/MockAsyncCollectionResult.cs index 86e871aa6987..5f1dae205813 100644 --- a/sdk/openai/tools/TestFramework/src/Mocks/MockAsyncCollectionResult.cs +++ b/sdk/openai/tools/TestFramework/src/Mocks/MockAsyncCollectionResult.cs @@ -2,7 +2,8 @@ // Licensed under the MIT License. using System.ClientModel; -using System.ClientModel.Primitives; +using System.Globalization; +using OpenAI.TestFramework.Adapters; namespace OpenAI.TestFramework.Mocks; @@ -13,6 +14,7 @@ namespace OpenAI.TestFramework.Mocks; public class MockAsyncCollectionResult : AsyncCollectionResult { private readonly Func> _enumerateAsyncFunc; + private readonly int _itemsPerPage; /// /// Initializes a new instance of the class @@ -20,13 +22,58 @@ public class MockAsyncCollectionResult : AsyncCollectionResult /// /// The function that asynchronously enumerates the values in the collection. /// The optional pipeline response. - public MockAsyncCollectionResult(Func> enumerateAsyncFunc, PipelineResponse? response = null) : - base(response ?? new MockPipelineResponse()) + public MockAsyncCollectionResult(Func> enumerateAsyncFunc, int itemsPerPage = 5) { + if (itemsPerPage < 1) + { + throw new ArgumentOutOfRangeException(nameof(itemsPerPage), "Items per page must be greater than 0."); + } + _enumerateAsyncFunc = enumerateAsyncFunc ?? throw new ArgumentNullException(nameof(enumerateAsyncFunc)); + _itemsPerPage = itemsPerPage; + } + + /// + public override ContinuationToken? GetContinuationToken(ClientResult page) + { + var parsed = MockPage.FromClientResult(page); + string token = parsed.Next.ToString(CultureInfo.InvariantCulture); + return ContinuationToken.FromBytes(BinaryData.FromString(token)); + } + + /// + public override async IAsyncEnumerable GetRawPagesAsync() + { + List items = new(_itemsPerPage); + int next = 0; + + await foreach (TValue item in _enumerateAsyncFunc()) + { + items.Add(item); + next++; + if (items.Count == _itemsPerPage) + { + yield return new MockPage + { + Values = items, + Next = next + }.AsClientResult(); + + items.Clear(); + } + } + + if (items.Count > 0) + { + yield return new MockPage + { + Values = items, + Next = next + }.AsClientResult(); + } } - /// - public override IAsyncEnumerator GetAsyncEnumerator(CancellationToken cancellationToken = default) - => _enumerateAsyncFunc().GetAsyncEnumerator(cancellationToken); + /// + protected override IAsyncEnumerable GetValuesFromPageAsync(ClientResult page) + => new SyncToAsyncEnumerable(MockPage.FromClientResult(page).Values); } diff --git a/sdk/openai/tools/TestFramework/src/Mocks/MockAsyncPageCollection.cs b/sdk/openai/tools/TestFramework/src/Mocks/MockAsyncPageCollection.cs deleted file mode 100644 index 424681252282..000000000000 --- a/sdk/openai/tools/TestFramework/src/Mocks/MockAsyncPageCollection.cs +++ /dev/null @@ -1,70 +0,0 @@ -// Copyright (c) Microsoft Corporation. All rights reserved. -// Licensed under the MIT License. - -using System.ClientModel; -using System.ClientModel.Primitives; - -namespace OpenAI.TestFramework.Mocks; - -/// -/// Represents a mock implementation of the class. -/// -/// The type of the values in the collection. -public class MockAsyncPageCollection : AsyncPageCollection -{ - private readonly Func> _enumerateAsyncFunc; - private readonly PipelineResponse _response; - private readonly int _itemsPerPage; - private PageResult? _currentPage; - - /// - /// Initializes a new instance. - /// - /// The function that enumerates the collection asynchronously. - /// The pipeline response. - public MockAsyncPageCollection(Func> enumerateAsyncFunc, PipelineResponse response, int itemsPerPage = 5) - { - if (itemsPerPage <= 0) - { - throw new ArgumentOutOfRangeException(nameof(itemsPerPage)); - } - - _enumerateAsyncFunc = enumerateAsyncFunc ?? throw new ArgumentNullException(nameof(enumerateAsyncFunc)); - _response = response; - _itemsPerPage = itemsPerPage; - } - - /// - protected override Task> GetCurrentPageAsyncCore() - => Task.FromResult(_currentPage ?? throw new InvalidOperationException("Please call MoveNextAsync first.")); - - /// - protected override async IAsyncEnumerator> GetAsyncEnumeratorCore(CancellationToken cancellationToken = default) - { - List items = new(_itemsPerPage); - int pageStart = 0; - int rolling = 0; - - await foreach (TValue value in _enumerateAsyncFunc()) - { - items.Add(value); - rolling++; - if (items.Count == _itemsPerPage) - { - _currentPage = PageResult.Create(items, ToContinuation(pageStart), ToContinuation(rolling), _response); - yield return _currentPage; - items.Clear(); - pageStart = rolling; - } - } - - if (items.Count > 0) - { - _currentPage = PageResult.Create(items, ToContinuation(pageStart), ToContinuation(rolling), _response); - yield return _currentPage; - } - } - - private static ContinuationToken ToContinuation(int offset) - => ContinuationToken.FromBytes(BinaryData.FromBytes(BitConverter.GetBytes(offset))); -} diff --git a/sdk/openai/tools/TestFramework/src/Mocks/MockCollectionResult.cs b/sdk/openai/tools/TestFramework/src/Mocks/MockCollectionResult.cs index e12e34b3428c..49b11923b67e 100644 --- a/sdk/openai/tools/TestFramework/src/Mocks/MockCollectionResult.cs +++ b/sdk/openai/tools/TestFramework/src/Mocks/MockCollectionResult.cs @@ -2,7 +2,7 @@ // Licensed under the MIT License. using System.ClientModel; -using System.ClientModel.Primitives; +using System.Globalization; namespace OpenAI.TestFramework.Mocks { @@ -13,24 +13,66 @@ namespace OpenAI.TestFramework.Mocks public class MockCollectionResult : CollectionResult { private readonly Func> _enumerateFunc; + private readonly int _itemsPerPage; /// /// Initializes a new instance of the class with the specified enumeration /// function and optional pipeline response. /// /// The function used to enumerate the collection. - /// The pipeline response associated with the collection. - public MockCollectionResult(Func> enumerateFunc, PipelineResponse? response = null) : - base(response ?? new MockPipelineResponse()) + /// The number of items per page. + public MockCollectionResult(Func> enumerateFunc, int itemsPerPage = 5) { + if (itemsPerPage < 1) + { + throw new ArgumentOutOfRangeException(nameof(itemsPerPage), "Items per page must be greater than 0."); + } + _enumerateFunc = enumerateFunc ?? throw new ArgumentNullException(nameof(enumerateFunc)); + _itemsPerPage = itemsPerPage; } - /// - /// Returns an enumerator that iterates through the collection. - /// - /// An enumerator that can be used to iterate through the collection. - public override IEnumerator GetEnumerator() - => _enumerateFunc().GetEnumerator(); + /// + public override IEnumerable GetRawPages() + { + List items = new(_itemsPerPage); + int next = 0; + foreach (TValue item in _enumerateFunc()) + { + items.Add(item); + next++; + if (items.Count == _itemsPerPage) + { + yield return new MockPage + { + Values = items, + Next = next + }.AsClientResult(); + + items.Clear(); + } + } + + if (items.Count > 0) + { + yield return new MockPage + { + Values = items, + Next = next + }.AsClientResult(); + } + } + + /// + public override ContinuationToken? GetContinuationToken(ClientResult page) + { + var parsed = MockPage.FromClientResult(page); + string token = parsed.Next.ToString(CultureInfo.InvariantCulture); + return ContinuationToken.FromBytes(BinaryData.FromString(token)); + } + + /// + protected override IEnumerable GetValuesFromPage(ClientResult page) + => MockPage.FromClientResult(page).Values; } } diff --git a/sdk/openai/tools/TestFramework/src/Mocks/MockPage.cs b/sdk/openai/tools/TestFramework/src/Mocks/MockPage.cs new file mode 100644 index 000000000000..830bbe9aa0c4 --- /dev/null +++ b/sdk/openai/tools/TestFramework/src/Mocks/MockPage.cs @@ -0,0 +1,47 @@ +// Copyright(c) Microsoft Corporation. All rights reserved. +// Licensed under the MIT License. + +using System.ClientModel; +using System.ClientModel.Primitives; + +namespace OpenAI.TestFramework.Mocks; + +/// +/// Represents a mock page with a collection of values and a reference to the next page. +/// +/// The type of values in the page. +public class MockPage +{ + /// + /// Gets or sets the collection of values in the page. + /// + required public IReadOnlyList Values { get; set; } + + /// + /// Gets or sets the first item on the next page. + /// + required public int Next { get; set; } + + /// + /// Creates a instance from a . + /// + /// The client result. + /// The created instance. + public static MockPage FromClientResult(ClientResult result) + { + PipelineResponse response = result.GetRawResponse(); + response.BufferContent(); + return response.Content.ToObjectFromJson>(); + } + + /// + /// Converts the instance to a . + /// + /// The converted instance. + public ClientResult AsClientResult() + { + var serialized = BinaryData.FromObjectAsJson(this); + var mockResponse = new MockPipelineResponse(content: serialized); + return ClientResult.FromResponse(mockResponse); + } +} diff --git a/sdk/openai/tools/TestFramework/src/Mocks/MockPageCollection.cs b/sdk/openai/tools/TestFramework/src/Mocks/MockPageCollection.cs deleted file mode 100644 index 1f08987aeb65..000000000000 --- a/sdk/openai/tools/TestFramework/src/Mocks/MockPageCollection.cs +++ /dev/null @@ -1,71 +0,0 @@ -// Copyright (c) Microsoft Corporation. All rights reserved. -// Licensed under the MIT License. - -using System.ClientModel; -using System.ClientModel.Primitives; - -namespace OpenAI.TestFramework.Mocks; - -/// -/// Represents a mock implementation of the class. -/// -/// The type of the values in the collection. -public class MockPageCollection : PageCollection -{ - private readonly Func> _enumerateFunc; - private readonly PipelineResponse _response; - private readonly int _itemsPerPage; - private PageResult? _currentPage; - - /// - /// Creates a new instance. - /// - /// The function used to enumerate the collection. - /// The pipeline response. - /// (Optional) The number of items per page. - public MockPageCollection(Func> enumerateFunc, PipelineResponse response, int itemsPerPage = 5) - { - if (itemsPerPage <= 0) - { - throw new ArgumentOutOfRangeException(nameof(itemsPerPage)); - } - - _enumerateFunc = enumerateFunc ?? throw new ArgumentNullException(nameof(enumerateFunc)); - _response = response; - _itemsPerPage = itemsPerPage; - } - - /// - protected override PageResult GetCurrentPageCore() - => _currentPage ?? throw new InvalidOperationException("Please call MoveNextAsync first."); - - /// - protected override IEnumerator> GetEnumeratorCore() - { - List items = new(_itemsPerPage); - int pageStart = 0; - int rolling = 0; - - foreach (TValue item in _enumerateFunc()) - { - items.Add(item); - rolling++; - if (items.Count == _itemsPerPage) - { - _currentPage = PageResult.Create(items, ToContinuation(pageStart), ToContinuation(rolling), _response); - yield return _currentPage; - items.Clear(); - pageStart = rolling; - } - } - - if (items.Count > 0) - { - _currentPage = PageResult.Create(items, ToContinuation(pageStart), null, _response); - yield return _currentPage; - } - } - - private static ContinuationToken ToContinuation(int offset) - => ContinuationToken.FromBytes(BinaryData.FromBytes(BitConverter.GetBytes(offset))); -} diff --git a/sdk/openai/tools/TestFramework/src/Mocks/MockPipelineResponse.cs b/sdk/openai/tools/TestFramework/src/Mocks/MockPipelineResponse.cs index 1ade396dfce6..72aecf0433fb 100644 --- a/sdk/openai/tools/TestFramework/src/Mocks/MockPipelineResponse.cs +++ b/sdk/openai/tools/TestFramework/src/Mocks/MockPipelineResponse.cs @@ -81,8 +81,8 @@ private async ValueTask BufferContentSyncAsync(bool isAsync, Cancell ? await BinaryData.FromStreamAsync(ContentStream, token).ConfigureAwait(false) : BinaryData.FromStream(ContentStream); - ContentStream?.Dispose(); - ContentStream = _buffered.ToStream(); + _contentStream?.Dispose(); + _contentStream = _buffered.ToStream(); return _buffered; } } diff --git a/sdk/openai/tools/TestFramework/src/Mocks/MockRestService.cs b/sdk/openai/tools/TestFramework/src/Mocks/MockRestService.cs index 58420f679331..eaebc97ac346 100644 --- a/sdk/openai/tools/TestFramework/src/Mocks/MockRestService.cs +++ b/sdk/openai/tools/TestFramework/src/Mocks/MockRestService.cs @@ -5,6 +5,7 @@ using System.Net; using System.Net.Sockets; using System.Text.Json; +using System.Text.Json.Serialization; using OpenAI.TestFramework.Utils; namespace OpenAI.TestFramework.Mocks; @@ -20,15 +21,7 @@ public class MockRestService : IDisposable /// /// The ID of the entry. /// The data associated with the entry. - public record Entry(string id, TData data) - { -#if NETFRAMEWORK - public Entry() : this(string.Empty, default!) - { - // .Net framework System.Text.Json cannot deserialize records without a parameterless constructor - } -#endif - }; + public record Entry(string id, TData data); /// /// Represents an error in the mock REST service. @@ -41,9 +34,7 @@ public record Error(int error, string message, string? stack = null); private static readonly JsonSerializerOptions s_options = new() { WriteIndented = true, -#pragma warning disable SYSLIB0020 - IgnoreNullValues = true -#pragma warning restore SYSLIB0020 + DefaultIgnoreCondition = JsonIgnoreCondition.WhenWritingNull }; private ConcurrentDictionary _data; @@ -395,7 +386,7 @@ private static Uri TerminatePathWithSlash(Uri uri) return default; } - return JsonHelpers.Deserialize(request.InputStream, s_options); + return JsonSerializer.Deserialize(request.InputStream, s_options); } private static void WriteJsonResponse(HttpListenerResponse response, int status, T data) @@ -403,7 +394,7 @@ private static void WriteJsonResponse(HttpListenerResponse response, int stat response.StatusCode = status; using MemoryStream buffer = new(); - JsonHelpers.Serialize(buffer, data, s_options); + JsonSerializer.Serialize(buffer, data, s_options); buffer.Seek(0, SeekOrigin.Begin); response.ContentType = "application/json"; diff --git a/sdk/openai/tools/TestFramework/src/Mocks/MockRestServiceClient.cs b/sdk/openai/tools/TestFramework/src/Mocks/MockRestServiceClient.cs index a3fb851d3968..74d2e40ad8ed 100644 --- a/sdk/openai/tools/TestFramework/src/Mocks/MockRestServiceClient.cs +++ b/sdk/openai/tools/TestFramework/src/Mocks/MockRestServiceClient.cs @@ -6,7 +6,7 @@ using System.ClientModel.Primitives; using System.Globalization; using System.Net.Http; -using OpenAI.TestFramework.Utils; +using System.Text.Json; namespace OpenAI.TestFramework.Mocks; @@ -241,7 +241,7 @@ protected async ValueTask SendSyncOrAsync(bool isAsync, HttpMethod else { using MemoryStream stream = new(); - JsonHelpers.Serialize(stream, data); + JsonSerializer.Serialize(stream, data); var binaryData = BinaryData.FromBytes(new ReadOnlyMemory(stream.GetBuffer(), 0, (int)stream.Length)); message.Request.Headers.Set("Content-Length", stream.Length.ToString(CultureInfo.InvariantCulture)); diff --git a/sdk/openai/tools/TestFramework/src/OpenAI.TestFramework.csproj b/sdk/openai/tools/TestFramework/src/OpenAI.TestFramework.csproj index cd6ec56f00b9..b29af0094d90 100644 --- a/sdk/openai/tools/TestFramework/src/OpenAI.TestFramework.csproj +++ b/sdk/openai/tools/TestFramework/src/OpenAI.TestFramework.csproj @@ -18,9 +18,7 @@ - - - + diff --git a/sdk/openai/tools/TestFramework/src/RecordedClientTestBase.cs b/sdk/openai/tools/TestFramework/src/RecordedClientTestBase.cs index 27d6ca2e7b2e..0409b774d340 100644 --- a/sdk/openai/tools/TestFramework/src/RecordedClientTestBase.cs +++ b/sdk/openai/tools/TestFramework/src/RecordedClientTestBase.cs @@ -48,7 +48,7 @@ public abstract class RecordedClientTestBase : ClientTestBase /// Creates a new instance. /// /// True to run the async version of a test, false to run the sync version of a test. - public RecordedClientTestBase(bool isAsync) : this(isAsync, null) + public RecordedClientTestBase(bool isAsync) : this(isAsync, null, null) { } /// @@ -56,10 +56,13 @@ public RecordedClientTestBase(bool isAsync) : this(isAsync, null) /// /// True to run the async version of a test, false to run the sync version of a test. /// (Optional) The recorded test mode to use. If unset, the default recorded test mode will be used. - public RecordedClientTestBase(bool isAsync, RecordedTestMode? mode = null) : base(isAsync) + /// (Optional) Whether or not to attempt to record automatically in the case of missing recordings + /// or recording mismatches. + public RecordedClientTestBase(bool isAsync, RecordedTestMode? mode = null, bool? automaticRecord = null) : base(isAsync) { _options = new TestRecordingOptions(); Mode = mode ?? GetDefaultRecordedTestMode(); + AutomaticRecord = automaticRecord ?? GetDefaultAutomaticRecordEnabled(); } /// @@ -75,6 +78,12 @@ public RecordedClientTestBase(bool isAsync, RecordedTestMode? mode = null) : bas /// public RecordedTestMode Mode { get; set; } + /// + /// Gets or sets whether or not we should attempt to record a test if there is a recording mismatch, or the recording + /// file is missing. + /// + public bool AutomaticRecord { get; set; } + /// /// Gets or sets the recording options to use for the current test. This will be pre-populated with a sensible configuration. /// @@ -157,6 +166,16 @@ public virtual bool UseFiddler } } + /// + /// Gets whether or not we are running the tests in CI/CD (e.g. GitHub workflows) + /// + public virtual bool IsRunningInCI => new string?[] + { + Environment.GetEnvironmentVariable("CI"), // GitHub workflows + Environment.GetEnvironmentVariable("TF_BUILD"), // Azure DevOps + } + .Any(s => s != null); + /// /// Checks if the recording has a recorded value for . If there is none, the /// will be added and return. Otherwise the existing value will be returned. @@ -328,6 +347,13 @@ public virtual TClientOptions ConfigureClientOptions(TClientOpti /// The test mode to use. protected virtual RecordedTestMode GetDefaultRecordedTestMode() => RecordedTestMode.Playback; + /// + /// Gets the default value for whether or not to automatically record a test if there is a recording mismatch, or the recording + /// file is missing. + /// + /// True or false. + protected virtual bool GetDefaultAutomaticRecordEnabled() => !IsRunningInCI; + /// /// Gets the name of recording JSON file that contains the recording. This will be based on a sanitized version /// of test name, and "Async" will be automatically appended when running the asynchronous versions of tests. diff --git a/sdk/openai/tools/TestFramework/src/RecordedTestAttribute.cs b/sdk/openai/tools/TestFramework/src/RecordedTestAttribute.cs index 81d94268cac9..5f98e8d75507 100644 --- a/sdk/openai/tools/TestFramework/src/RecordedTestAttribute.cs +++ b/sdk/openai/tools/TestFramework/src/RecordedTestAttribute.cs @@ -1,7 +1,12 @@ // Copyright (c) Microsoft Corporation. All rights reserved. // Licensed under the MIT License. +using System.Text; using NUnit.Framework; +using NUnit.Framework.Interfaces; +using NUnit.Framework.Internal.Commands; +using NUnit.Framework.Internal; +using OpenAI.TestFramework.Recording; namespace OpenAI.TestFramework; @@ -10,9 +15,118 @@ namespace OpenAI.TestFramework; /// in your test class, and add this attribute to your test function, and then /// make sure to call /// on the client options you use to configure a client, this should automatically enable the recording/playback -/// functionality. +/// functionality. By default. this will also automatically try to re-record the test if it fails during playback. /// [AttributeUsage(AttributeTargets.Method, AllowMultiple = false, Inherited = true)] -public class RecordedTestAttribute : TestAttribute +public class RecordedTestAttribute : TestAttribute, IRepeatTest { + /// + /// Whether or not to automatically try to record the test again in the case of a recording mismatch, or missing + /// test recording. + /// + public bool AutomaticRecord { get; set; } = true; + + public TestCommand Wrap(TestCommand command) + { + // For some reason, the test fixture may be set on the parent of the current test, and not the current test + // itself. Let's handle this + ITest? test = command.Test; + while (test.Fixture == null && test.Parent != null) + { + test = test.Parent; + } + + // If the test fixture extends RecordedClientTestBase, we are in playback mode, and auto-rerecord + // is enabled, wrap the command to enable the retry in Record mode + if (AutomaticRecord + && test?.Fixture is RecordedClientTestBase testBase + && testBase.AutomaticRecord + && testBase.Mode == RecordedTestMode.Playback) + { + return new AutoRerecordCommand(command, testBase); + } + + return command; + } + + private class AutoRerecordCommand(TestCommand inner, RecordedClientTestBase testBase) : DelegatingTestCommand(inner) + { + private readonly RecordedClientTestBase _testBase = testBase ?? throw new ArgumentNullException(nameof(testBase)); + + public override TestResult Execute(TestExecutionContext context) + { + context.CurrentResult = innerCommand.Execute(context); + if (IsRecordingPlaybackFailure(context.CurrentResult)) + { + try + { + _testBase.Mode = RecordedTestMode.Record; + TestResult originalResult = context.CurrentResult; + + context.CurrentResult = context.CurrentTest.MakeTestResult(); + context.CurrentResult = innerCommand.Execute(context); + + // If the recording succeeded, update the original message to reflect this + ResultState state; + string? stackTrace; + StringBuilder builder = new(); + if (context.CurrentResult.ResultState?.Status == TestStatus.Passed) + { + state = originalResult.ResultState; + stackTrace = originalResult.StackTrace; + builder.AppendLine("Test failed playback, but was successfully re-recorded. It should pass if re-run."); + } + else + { + state = context.CurrentResult.ResultState ?? ResultState.Error; + stackTrace = context.CurrentResult.StackTrace; + builder.AppendLine("Re-recording attempt failed. Error: "); + builder.AppendLine(); + builder.AppendLine(context.CurrentResult.Message); + builder.AppendLine(); + builder.AppendLine("Original message:"); + } + + builder.AppendLine(); + builder.Append(originalResult.Message); + context.CurrentResult.SetResult(state, builder.ToString(), stackTrace); + } + finally + { + _testBase.Mode = RecordedTestMode.Playback; + } + } + + return context.CurrentResult; + } + + private static bool IsRecordingPlaybackFailure(TestResult result) + { + string exceptionName = typeof(TestRecordingMismatchException).FullName + ?? nameof(TestRecordingMismatchException); + + // 1. Check if the test passed + bool testPassed = result.ResultState?.Status switch + { + TestStatus.Passed => true, + TestStatus.Inconclusive => true, + TestStatus.Skipped => true, + _ => false + }; + + if (testPassed) + { + return false; + } + + // 2. Check if the failure message indicates a recording playback exception. This sadly requires us to check test failure + // messages which can be a little fragile but there does not seem to be a way to get the exception directly + if (result.Message?.Contains(exceptionName) == true) + { + return true; + } + + return false; + } + } } diff --git a/sdk/openai/tools/TestFramework/src/Recording/Proxy/ProxyClientResult.cs b/sdk/openai/tools/TestFramework/src/Recording/Proxy/ProxyClientResult.cs index a1e16d300d52..8598c3db2f12 100644 --- a/sdk/openai/tools/TestFramework/src/Recording/Proxy/ProxyClientResult.cs +++ b/sdk/openai/tools/TestFramework/src/Recording/Proxy/ProxyClientResult.cs @@ -15,14 +15,9 @@ public class ProxyClientResult : ClientResult /// /// Initializes a new instance of the class. /// - /// (Optional) The pipeline response. - public ProxyClientResult(PipelineResponse? response = null) - { - if (response != null) - { - SetRawResponse(response); - } - } + /// The pipeline response. + public ProxyClientResult(PipelineResponse response) : base(response) + { } /// /// Gets the recording ID from the response headers. @@ -40,14 +35,10 @@ public class ProxyClientResult : ProxyClientResult /// Initializes a new instance of the class. /// /// The result value. - /// (Optional) The pipeline response. - public ProxyClientResult(TResult value, PipelineResponse? response = null) + /// The pipeline response. + public ProxyClientResult(TResult value, PipelineResponse response) : base(response) { Value = value; - if (response != null) - { - SetRawResponse(response); - } } /// diff --git a/sdk/openai/tools/TestFramework/src/Utils/Default.cs b/sdk/openai/tools/TestFramework/src/Utils/Default.cs index 5774a477498a..fb27ef47b74b 100644 --- a/sdk/openai/tools/TestFramework/src/Utils/Default.cs +++ b/sdk/openai/tools/TestFramework/src/Utils/Default.cs @@ -33,11 +33,7 @@ public static class Default PropertyNameCaseInsensitive = true, PropertyNamingPolicy = JsonNamingPolicy.CamelCase, WriteIndented = true, -#if NET DefaultIgnoreCondition = JsonIgnoreCondition.WhenWritingNull, -#else - IgnoreNullValues = true, -#endif }; /// @@ -52,8 +48,8 @@ public static JsonSerializerOptions RecordingJsonOptions _recordingJsonOptions = InnerRecordingJsonOptions.Clone(); _recordingJsonOptions.Converters.Add( -#if NET6_0 - // .Net 6.0 seems to have a weird bug here. This is not needed for .Net framework, nor .Net 7+ +#if !NET7_0_OR_GREATER + // System.Text.Json 6.0.9 seems to have a weird bug here. This is not needed for .Net 7+ new Utf8JsonSerializableConverterFactory() #else new Utf8JsonSerializableConverter() @@ -73,11 +69,7 @@ public static JsonSerializerOptions RecordingJsonOptions { PropertyNameCaseInsensitive = true, WriteIndented = true, -#if NET DefaultIgnoreCondition = JsonIgnoreCondition.WhenWritingNull, -#else - IgnoreNullValues = true, -#endif }; /// diff --git a/sdk/openai/tools/TestFramework/src/Utils/Extensions.cs b/sdk/openai/tools/TestFramework/src/Utils/Extensions.cs index 437e8dc05b7a..a8a33b26cc07 100644 --- a/sdk/openai/tools/TestFramework/src/Utils/Extensions.cs +++ b/sdk/openai/tools/TestFramework/src/Utils/Extensions.cs @@ -1,9 +1,10 @@ // Copyright (c) Microsoft Corporation. All rights reserved. // Licensed under the MIT License. -using System.ClientModel; using System.ClientModel.Primitives; using System.Diagnostics; +using System.Text.Json; +using System.Text.Json.Serialization; namespace OpenAI.TestFramework.Utils; @@ -301,23 +302,6 @@ public static async Task> ToListAsync(this IAsyncEnumerable asyncE } return list; } - - /// - /// Converts an async enumerable of pages to a asynchronously. - /// - /// The type of the elements in the enumerable. - /// The to convert. - /// The cancellation token. - /// Asynchronous task to do the conversion. - public static async Task> ToListAsync(this IAsyncEnumerable> pageAsyncEnumerable, CancellationToken token = default) - { - List list = new List(); - await foreach(PageResult page in pageAsyncEnumerable.WithCancellation(token)) - { - list.AddRange(page.Values); - } - return list; - } } /// @@ -412,3 +396,30 @@ public static bool IsAssignableToOpen(this Type type, Type openGeneric) return openGeneric.IsAssignableFrom(type.GetGenericTypeDefinition()); } } + +/// +/// Extensions for JSON serialization/deserialization. +/// +public static class JsonExtensions +{ + /// + /// Creates a clone of the specified JSON serializer options. + /// + /// The JSON serializer options to clone. + /// (Optional) Filter to apply for selecting specific converters to include in the cloned options. + /// A clone of the JSON serializer options. + public static JsonSerializerOptions Clone(this JsonSerializerOptions options, Predicate? converterFilter = null) + { + JsonSerializerOptions cloned = new JsonSerializerOptions(options); + if (converterFilter != null) + { + cloned.Converters.Clear(); + foreach (var converter in options.Converters.Where(c => converterFilter(c))) + { + cloned.Converters.Add(converter); + } + } + + return cloned; + } +} \ No newline at end of file diff --git a/sdk/openai/tools/TestFramework/src/Utils/JsonHelpers.cs b/sdk/openai/tools/TestFramework/src/Utils/JsonHelpers.cs deleted file mode 100644 index ed6752ca4c30..000000000000 --- a/sdk/openai/tools/TestFramework/src/Utils/JsonHelpers.cs +++ /dev/null @@ -1,143 +0,0 @@ -// Copyright (c) Microsoft Corporation. All rights reserved. -// Licensed under the MIT License. - -using System.Text.Json; -using System.Text.Json.Serialization; - -namespace OpenAI.TestFramework.Utils; - -public static class JsonHelpers -{ - /// - /// Serializes the specified data to a stream using as a UTF-8 encoded JSON text. - /// - /// The type of the data to serialize. - /// The stream to write the serialized data to. - /// The data to serialize. - /// (Optional) Options to use when serializing. - public static void Serialize(Stream stream, T data, JsonSerializerOptions? options = null) - { -#if NETFRAMEWORK - using (Utf8JsonWriter writer = new(stream)) - { - JsonSerializer.Serialize(writer, data, options); - writer.Flush(); - } -#else - JsonSerializer.Serialize(stream, data, options); -#endif - } - - /// - /// Deserializes UTF-8 encoded JSON text from a stream. - /// - /// The type of the data to deserialize. - /// The stream to read the serialized data from. - /// (Optional) Options to use when deserializing. - /// The deserialized data. - public static T? Deserialize(Stream stream, JsonSerializerOptions? options = null) - { -#if NETFRAMEWORK - // For now let's keep it simple and load entire JSON bytes into memory - using MemoryStream buffer = new(); - stream.CopyTo(buffer); - - ReadOnlySpan jsonBytes = buffer.GetBuffer().AsSpan(0, (int)buffer.Length); - return JsonSerializer.Deserialize(jsonBytes, options); -#else - return JsonSerializer.Deserialize(stream, options); -#endif - } - -#if NET6_0_OR_GREATER - // .Net 6 and newer already have the extension method we need defined in JsonSerializer -#else - // TODO FIXME once we move to newer versions of System.Text.Json we can directly use the - // JsonSerializer extension method for elements - public static T? Deserialize(this JsonElement element, JsonSerializerOptions? options = null) - { - using MemoryStream stream = new(); - using Utf8JsonWriter writer = new(stream, new() - { - Encoder = System.Text.Encodings.Web.JavaScriptEncoder.UnsafeRelaxedJsonEscaping, - Indented = false, - SkipValidation = true - }); - element.WriteTo(writer); - writer.Flush(); - - stream.Seek(0, SeekOrigin.Begin); - if (((ulong)stream.Length & 0xffffffff00000000) != 0ul) - { - throw new ArgumentOutOfRangeException("JsonElement is too large"); - } - - ReadOnlySpan span = new(stream.GetBuffer(), 0, (int)stream.Length); - return JsonSerializer.Deserialize(span, options); - } -#endif - - /// - /// Serializes a value to a JsonElement. - /// - /// Type of the data to serialize. - /// The value to serialize. - /// (Optional) Options to use when serializing. - /// The serialized value as a JsonElement. - public static JsonElement SerializeToElement(T value, JsonSerializerOptions? options = null) - { -#if NET6_0_OR_GREATER - return JsonSerializer.SerializeToElement(value, options); -#else - using MemoryStream stream = new(); - Serialize(stream, value, options); - stream.Seek(0, SeekOrigin.Begin); - return JsonDocument.Parse(stream).RootElement; -#endif - } - - /// - /// Creates a clone of the specified JSON serializer options. - /// - /// The JSON serializer options to clone. - /// (Optional) Filter to apply for selecting specific converters to include in the cloned options. - /// A clone of the JSON serializer options. - public static JsonSerializerOptions Clone(this JsonSerializerOptions options, Predicate? converterFilter = null) - { -#if NET - JsonSerializerOptions cloned = new JsonSerializerOptions(options); - if (converterFilter != null) - { - cloned.Converters.Clear(); - foreach (var converter in options.Converters.Where(c => converterFilter(c))) - { - cloned.Converters.Add(converter); - } - } - - return cloned; -#else - JsonSerializerOptions clone = new() - { - AllowTrailingCommas = options.AllowTrailingCommas, - DefaultBufferSize = options.DefaultBufferSize, - DictionaryKeyPolicy = options.DictionaryKeyPolicy, - Encoder = options.Encoder, - IgnoreNullValues = options.IgnoreNullValues, - IgnoreReadOnlyProperties = options.IgnoreReadOnlyProperties, - MaxDepth = options.MaxDepth, - PropertyNameCaseInsensitive = options.PropertyNameCaseInsensitive, - PropertyNamingPolicy = options.PropertyNamingPolicy, - ReadCommentHandling = options.ReadCommentHandling, - WriteIndented = options.WriteIndented, - }; - - foreach (var converter in options.Converters.Where(c => converterFilter?.Invoke(c) ?? true)) - { - clone.Converters.Add(converter); - } - - return clone; -#endif - } -} diff --git a/sdk/openai/Azure.AI.OpenAI/tests/Utils/NonPublic.cs b/sdk/openai/tools/TestFramework/src/Utils/NonPublic.cs similarity index 65% rename from sdk/openai/Azure.AI.OpenAI/tests/Utils/NonPublic.cs rename to sdk/openai/tools/TestFramework/src/Utils/NonPublic.cs index f890e4e75b8a..50cbee512137 100644 --- a/sdk/openai/Azure.AI.OpenAI/tests/Utils/NonPublic.cs +++ b/sdk/openai/tools/TestFramework/src/Utils/NonPublic.cs @@ -1,9 +1,9 @@ -#nullable enable +// Copyright (c) Microsoft Corporation. All rights reserved. +// Licensed under the MIT License. -using System; using System.Reflection; -namespace Azure.AI.OpenAI.Tests.Utils; +namespace OpenAI.TestFramework.Utils; /// /// Helpers to make accessing the many internal or private members of the Azure test framework more streamlined @@ -78,6 +78,56 @@ public static Accessor FromField(string fieldName) w return new Accessor(getter, setter); } + /// + /// Creates a delegate from an internal, protected, or private parameterless method. + /// + /// The type of the class that defines this method. + /// The return type of the method. + /// The name of the method. + /// The function delegate that can be used to access the method. + /// If no method could be found with the specified name and signature. + public static Func FromMethod(string methodName) where TObj : class + { + MethodInfo? method = GetMethod(methodName, []); + return (Func)method.CreateDelegate(typeof(Func)); + } + + /// + /// Creates a delegate from an internal, protected, or private parameterless method. + /// + /// The type of the class that defines this method. + /// The type of the first method argument. + /// The return type of the method. + /// The name of the method. + /// The function delegate that can be used to access the method. + /// If no method could be found with the specified name and signature. + public static Func FromMethod(string methodName) where TObj : class + { + MethodInfo method = GetMethod(methodName, [typeof(TArg)]); + return (Func)method.CreateDelegate(typeof(Func)); + } + + private static MethodInfo GetMethod(string methodName, Type[] argTypes) + { + MethodInfo? method = typeof(TObj).GetMethod( + methodName, + BindingFlags.NonPublic | BindingFlags.Public | BindingFlags.Instance, + null, + argTypes, + null)!; + + if (method == null) + { + throw new ArgumentException($"'{methodName}' method could not be found in '{typeof(TObj).FullName}'"); + } + else if (!typeof(TRet).IsAssignableFrom(method.ReturnType)) + { + throw new ArgumentException($"'{methodName}' method does not return '{typeof(TRet).FullName}'"); + } + + return method; + } + /// /// The accessor struct that makes accessing internal, protected, or private properties/fields easier. /// @@ -93,7 +143,7 @@ public Accessor(Func? getter, Action? setter) HasGet = getter != null; _getter = getter ?? (_ => throw new InvalidOperationException("Get is not supported")); HasSet = setter != null; - _setter = setter ?? ((_, __) => throw new InvalidOperationException("Get is not supported")); + _setter = setter ?? ((_, __) => throw new InvalidOperationException("Set is not supported")); } /// diff --git a/sdk/openai/tools/TestFramework/src/Utils/Utf8JsonSerializableConverter.cs b/sdk/openai/tools/TestFramework/src/Utils/Utf8JsonSerializableConverter.cs index 3613f66c0349..5ed839e80e73 100644 --- a/sdk/openai/tools/TestFramework/src/Utils/Utf8JsonSerializableConverter.cs +++ b/sdk/openai/tools/TestFramework/src/Utils/Utf8JsonSerializableConverter.cs @@ -31,11 +31,10 @@ public override void Write(Utf8JsonWriter writer, IUtf8JsonSerializable value, J => value.Write(writer); } -#if NET6_0 +#if !NET7_0_OR_GREATER /// -/// .Net 6.0 has some odd quirks and is particularly pedantic with converters so directly using Utf8JsonSerializableConverter would -/// result in an InvalidCastException. The work around is to use a converter factory. Thankfully, neither .Net Framework, nor .Net 7+ -/// exhibit this behavior. +/// In versions of .Net older than 7.0, System.Text.Json version 6.0.9 has an odd quirk and is particularly pedantic with converters +/// so directly using Utf8JsonSerializableConverter would result in an InvalidCastException. The work around is to use a converter factory. /// public class Utf8JsonSerializableConverterFactory : JsonConverterFactory { diff --git a/sdk/openai/tools/TestFramework/tests/AdaptersTests.cs b/sdk/openai/tools/TestFramework/tests/AdaptersTests.cs index 266d388a3537..a231045cdc60 100644 --- a/sdk/openai/tools/TestFramework/tests/AdaptersTests.cs +++ b/sdk/openai/tools/TestFramework/tests/AdaptersTests.cs @@ -1,7 +1,6 @@ // Copyright (c) Microsoft Corporation. All rights reserved. // Licensed under the MIT License. -using System.ClientModel; using System.Diagnostics; using NUnit.Framework; using OpenAI.TestFramework.Adapters; @@ -64,42 +63,6 @@ public async Task TestFailedSyncToAsyncResultCollection() Assert.ThrowsAsync(() => asyncEnumerator.MoveNextAsync().AsTask()); } - [Test] - public async Task TestSyncToAsyncPageableCollection() - { - const int start = 0; - const int num = 100; - const int itemsPerPage = 10; - int expectedPages = (int)Math.Ceiling((double)num / itemsPerPage); - - MockPageCollection sync = new(() => Enumerable.Range(start, num), new MockPipelineResponse(), itemsPerPage); - SyncToAsyncPageCollection asyncAdapter = new(sync); - - int numPages = 0; - int expected = 0; - await foreach (var page in asyncAdapter) - { - numPages++; - foreach (int actual in page.Values) - { - Assert.That(actual, Is.EqualTo(expected)); - expected++; - } - } - - Assert.That(numPages, Is.EqualTo(expectedPages)); - } - - [Test] - public async Task TestFailedSyncToAsyncPageableCollection() - { - MockPageCollection sync = new(Fail, new MockPipelineResponse()); - SyncToAsyncPageCollection asyncAdapter = new(sync); - - await using var asyncEnumerator = ((IAsyncEnumerable>)asyncAdapter).GetAsyncEnumerator(Token); - Assert.ThrowsAsync(() => asyncEnumerator.MoveNextAsync().AsTask()); - } - private static IEnumerable Fail() { throw new ApplicationException("This should fail"); diff --git a/sdk/openai/tools/TestFramework/tests/AutoSyncAsyncTests.cs b/sdk/openai/tools/TestFramework/tests/AutoSyncAsyncTests.cs index 44f13bee39f1..877630552df3 100644 --- a/sdk/openai/tools/TestFramework/tests/AutoSyncAsyncTests.cs +++ b/sdk/openai/tools/TestFramework/tests/AutoSyncAsyncTests.cs @@ -101,9 +101,6 @@ public async Task ResultCollectionWorks() AsyncCollectionResult coll = client.ResultCollectionAsync(num, increment); Assert.IsNotNull(coll); - Assert.That(coll.GetRawResponse(), Is.Not.Null); - Assert.That(coll.GetRawResponse().Status, Is.EqualTo(200)); - Assert.That(coll.GetRawResponse().ReasonPhrase, Is.EqualTo("OK")); int numResults = 0; await foreach (int i in coll) @@ -134,57 +131,6 @@ public void FailedResultCollection() AssertCorrectFunctionCalled(client); } - [Test] - public async Task PageableCollectionWorks() - { - const int num = 50; - const int increment = 1; - const int itemsPerPage = 20; - int expectedPages = (int)Math.Ceiling((double)num / itemsPerPage); - - MockClient client = WrapClient(new MockClient()); - AsyncPageCollection coll = client.PageableCollectionAsync(num, increment, itemsPerPage); - Assert.IsNotNull(coll); - - int numPages = 0; - int numResults = 0; - await foreach(PageResult page in coll) - { - Assert.That(page.GetRawResponse(), Is.Not.Null); - Assert.That(page.GetRawResponse().Status, Is.EqualTo(200)); - Assert.That(page.GetRawResponse().ReasonPhrase, Is.EqualTo("OK")); - - numPages++; - foreach (int actual in page.Values) - { - Assert.That(actual, Is.EqualTo(numResults * increment)); - numResults++; - } - } - - Assert.That(numResults, Is.EqualTo(num)); - Assert.That(numPages, Is.EqualTo(expectedPages)); - AssertCorrectFunctionCalled(client); - } - - [Test] - public void FailedPageableCollection() - { - MockClient client = WrapClient(new MockClient()); - - // For now we mimic how the OpenAI and Azure OpenAI libraries work in that no service requests are sent - // until we try to enumerate the async collections. So exceptions aren't expected initially - AsyncPageCollection coll = client.FailPageableCollectionAsync(EX_MSG); - Assert.That(coll, Is.Not.Null); - - IAsyncEnumerator> enumerator = ((IAsyncEnumerable>)coll).GetAsyncEnumerator(); - Assert.That(enumerator, Is.Not.Null); - ArgumentException? ex = Assert.ThrowsAsync(() => enumerator.MoveNextAsync().AsTask()); - Assert.That(ex, Is.Not.Null); - Assert.That(ex!.Message, Is.EqualTo(EX_MSG)); - AssertCorrectFunctionCalled(client); - } - private void AssertCorrectFunctionCalled(MockClient client, int expectedCalls = 1) { if (IsAsync) diff --git a/sdk/openai/tools/TestFramework/tests/Helpers/MockClient.cs b/sdk/openai/tools/TestFramework/tests/Helpers/MockClient.cs index 9eac6054d6f0..b095f23f7d56 100644 --- a/sdk/openai/tools/TestFramework/tests/Helpers/MockClient.cs +++ b/sdk/openai/tools/TestFramework/tests/Helpers/MockClient.cs @@ -87,30 +87,6 @@ public virtual CollectionResult FailResultCollection(string message) return new MockCollectionResult(() => FailEnumerate(message)); } - public virtual AsyncPageCollection PageableCollectionAsync(int num, int increment, int itemsPerPage) - { - Interlocked.Increment(ref _asyncHit); - return new MockAsyncPageCollection(() => EnumerateAsync(num, increment), new MockPipelineResponse(), itemsPerPage); - } - - public virtual PageCollection PageableCollection(int num, int increment, int itemsPerPage) - { - Interlocked.Increment(ref _syncHit); - return new MockPageCollection(() => Enumerate(num, increment), new MockPipelineResponse(), itemsPerPage); - } - - public virtual AsyncPageCollection FailPageableCollectionAsync(string message) - { - Interlocked.Increment(ref _asyncHit); - return new MockAsyncPageCollection(() => FailEnumerateAsync(message), new MockPipelineResponse()); - } - - public virtual PageCollection FailPageableCollection(string message) - { - Interlocked.Increment(ref _syncHit); - return new MockPageCollection(() => FailEnumerate(message), new MockPipelineResponse()); - } - private async IAsyncEnumerable EnumerateAsync(int num, int increment, [EnumeratorCancellation] CancellationToken token = default) { int running = 0; diff --git a/sdk/openai/tools/TestFramework/tests/OpenAI.TestFramework.Tests.csproj b/sdk/openai/tools/TestFramework/tests/OpenAI.TestFramework.Tests.csproj index fd0abb7300a3..eb4db4704941 100644 --- a/sdk/openai/tools/TestFramework/tests/OpenAI.TestFramework.Tests.csproj +++ b/sdk/openai/tools/TestFramework/tests/OpenAI.TestFramework.Tests.csproj @@ -1,7 +1,7 @@  - $(RequiredTargetFrameworks);net8.0 + $(RequiredTargetFrameworks) enable enable latest @@ -16,8 +16,6 @@ - - diff --git a/sdk/search/Azure.Search.Documents/tests/Azure.Search.Documents.Tests.csproj b/sdk/search/Azure.Search.Documents/tests/Azure.Search.Documents.Tests.csproj index b23eadc79318..a3488793eb89 100644 --- a/sdk/search/Azure.Search.Documents/tests/Azure.Search.Documents.Tests.csproj +++ b/sdk/search/Azure.Search.Documents/tests/Azure.Search.Documents.Tests.csproj @@ -28,6 +28,7 @@ +