diff --git a/eng/Versions.props b/eng/Versions.props index 3c01e6cdc7b..5f0fdaa801f 100644 --- a/eng/Versions.props +++ b/eng/Versions.props @@ -2,7 +2,7 @@ 10 0 - 0 + 1 preview 1 $(MajorVersion).$(MinorVersion).$(PatchVersion) diff --git a/eng/packages/General.props b/eng/packages/General.props index 503e2c1c321..4dafd30a2fa 100644 --- a/eng/packages/General.props +++ b/eng/packages/General.props @@ -21,7 +21,7 @@ - + @@ -32,6 +32,7 @@ + diff --git a/src/Libraries/Microsoft.Extensions.AI.Abstractions/CHANGELOG.md b/src/Libraries/Microsoft.Extensions.AI.Abstractions/CHANGELOG.md index e8c2ea1e971..27ea54794b0 100644 --- a/src/Libraries/Microsoft.Extensions.AI.Abstractions/CHANGELOG.md +++ b/src/Libraries/Microsoft.Extensions.AI.Abstractions/CHANGELOG.md @@ -1,5 +1,10 @@ # Release History +## 10.0.0 + +- Added experimental `HostedImageGenerationTool`. +- Updated .NET dependencies to 10.0.0 versions. + ## 9.10.2 - Updated `AIFunctionFactory` to respect `[DisplayName(...)]` on functions as a way to override the function name. diff --git a/src/Libraries/Microsoft.Extensions.AI.Abstractions/ChatCompletion/ChatOptions.cs b/src/Libraries/Microsoft.Extensions.AI.Abstractions/ChatCompletion/ChatOptions.cs index 738f724dcd2..fe6ef70187c 100644 --- a/src/Libraries/Microsoft.Extensions.AI.Abstractions/ChatCompletion/ChatOptions.cs +++ b/src/Libraries/Microsoft.Extensions.AI.Abstractions/ChatCompletion/ChatOptions.cs @@ -197,7 +197,7 @@ protected ChatOptions(ChatOptions? other) /// [Experimental("MEAI001")] [JsonIgnore] - public object? ContinuationToken { get; set; } + public ResponseContinuationToken? ContinuationToken { get; set; } /// /// Gets or sets a callback responsible for creating the raw representation of the chat options from an underlying implementation. diff --git a/src/Libraries/Microsoft.Extensions.AI.Abstractions/ChatCompletion/ChatResponse.cs b/src/Libraries/Microsoft.Extensions.AI.Abstractions/ChatCompletion/ChatResponse.cs index 6f7ca4eeda2..1b535b3a244 100644 --- a/src/Libraries/Microsoft.Extensions.AI.Abstractions/ChatCompletion/ChatResponse.cs +++ b/src/Libraries/Microsoft.Extensions.AI.Abstractions/ChatCompletion/ChatResponse.cs @@ -102,7 +102,7 @@ public IList Messages /// [Experimental("MEAI001")] [JsonIgnore] - public object? ContinuationToken { get; set; } + public ResponseContinuationToken? ContinuationToken { get; set; } /// Gets or sets the raw representation of the chat response from an underlying implementation. /// diff --git a/src/Libraries/Microsoft.Extensions.AI.Abstractions/ChatCompletion/ChatResponseUpdate.cs b/src/Libraries/Microsoft.Extensions.AI.Abstractions/ChatCompletion/ChatResponseUpdate.cs index f1ad70cd22f..22f0dde1530 100644 --- a/src/Libraries/Microsoft.Extensions.AI.Abstractions/ChatCompletion/ChatResponseUpdate.cs +++ b/src/Libraries/Microsoft.Extensions.AI.Abstractions/ChatCompletion/ChatResponseUpdate.cs @@ -172,7 +172,7 @@ public IList Contents /// [Experimental("MEAI001")] [JsonIgnore] - public object? ContinuationToken { get; set; } + public ResponseContinuationToken? ContinuationToken { get; set; } /// Gets a object to display in the debugger display. [DebuggerBrowsable(DebuggerBrowsableState.Never)] diff --git a/src/Libraries/Microsoft.Extensions.AI.Abstractions/CompatibilitySuppressions.xml b/src/Libraries/Microsoft.Extensions.AI.Abstractions/CompatibilitySuppressions.xml index 8488d3969c4..993fd3d3ff0 100644 --- a/src/Libraries/Microsoft.Extensions.AI.Abstractions/CompatibilitySuppressions.xml +++ b/src/Libraries/Microsoft.Extensions.AI.Abstractions/CompatibilitySuppressions.xml @@ -1,6 +1,27 @@  + + CP0002 + M:Microsoft.Extensions.AI.ChatOptions.get_ContinuationToken + lib/net462/Microsoft.Extensions.AI.Abstractions.dll + lib/net462/Microsoft.Extensions.AI.Abstractions.dll + true + + + CP0002 + M:Microsoft.Extensions.AI.ChatResponse.get_ContinuationToken + lib/net462/Microsoft.Extensions.AI.Abstractions.dll + lib/net462/Microsoft.Extensions.AI.Abstractions.dll + true + + + CP0002 + M:Microsoft.Extensions.AI.ChatResponseUpdate.get_ContinuationToken + lib/net462/Microsoft.Extensions.AI.Abstractions.dll + lib/net462/Microsoft.Extensions.AI.Abstractions.dll + true + CP0002 M:Microsoft.Extensions.AI.HostedMcpServerTool.get_Headers @@ -22,6 +43,27 @@ lib/net462/Microsoft.Extensions.AI.Abstractions.dll true + + CP0002 + M:Microsoft.Extensions.AI.ChatOptions.get_ContinuationToken + lib/net8.0/Microsoft.Extensions.AI.Abstractions.dll + lib/net8.0/Microsoft.Extensions.AI.Abstractions.dll + true + + + CP0002 + M:Microsoft.Extensions.AI.ChatResponse.get_ContinuationToken + lib/net8.0/Microsoft.Extensions.AI.Abstractions.dll + lib/net8.0/Microsoft.Extensions.AI.Abstractions.dll + true + + + CP0002 + M:Microsoft.Extensions.AI.ChatResponseUpdate.get_ContinuationToken + lib/net8.0/Microsoft.Extensions.AI.Abstractions.dll + lib/net8.0/Microsoft.Extensions.AI.Abstractions.dll + true + CP0002 M:Microsoft.Extensions.AI.HostedMcpServerTool.get_Headers @@ -43,6 +85,27 @@ lib/net8.0/Microsoft.Extensions.AI.Abstractions.dll true + + CP0002 + M:Microsoft.Extensions.AI.ChatOptions.get_ContinuationToken + lib/net9.0/Microsoft.Extensions.AI.Abstractions.dll + lib/net9.0/Microsoft.Extensions.AI.Abstractions.dll + true + + + CP0002 + M:Microsoft.Extensions.AI.ChatResponse.get_ContinuationToken + lib/net9.0/Microsoft.Extensions.AI.Abstractions.dll + lib/net9.0/Microsoft.Extensions.AI.Abstractions.dll + true + + + CP0002 + M:Microsoft.Extensions.AI.ChatResponseUpdate.get_ContinuationToken + lib/net9.0/Microsoft.Extensions.AI.Abstractions.dll + lib/net9.0/Microsoft.Extensions.AI.Abstractions.dll + true + CP0002 M:Microsoft.Extensions.AI.HostedMcpServerTool.get_Headers @@ -64,6 +127,27 @@ lib/net9.0/Microsoft.Extensions.AI.Abstractions.dll true + + CP0002 + M:Microsoft.Extensions.AI.ChatOptions.get_ContinuationToken + lib/netstandard2.0/Microsoft.Extensions.AI.Abstractions.dll + lib/netstandard2.0/Microsoft.Extensions.AI.Abstractions.dll + true + + + CP0002 + M:Microsoft.Extensions.AI.ChatResponse.get_ContinuationToken + lib/netstandard2.0/Microsoft.Extensions.AI.Abstractions.dll + lib/netstandard2.0/Microsoft.Extensions.AI.Abstractions.dll + true + + + CP0002 + M:Microsoft.Extensions.AI.ChatResponseUpdate.get_ContinuationToken + lib/netstandard2.0/Microsoft.Extensions.AI.Abstractions.dll + lib/netstandard2.0/Microsoft.Extensions.AI.Abstractions.dll + true + CP0002 M:Microsoft.Extensions.AI.HostedMcpServerTool.get_Headers diff --git a/src/Libraries/Microsoft.Extensions.AI.Abstractions/Microsoft.Extensions.AI.Abstractions.json b/src/Libraries/Microsoft.Extensions.AI.Abstractions/Microsoft.Extensions.AI.Abstractions.json index b5ef3774b45..26512c88a28 100644 --- a/src/Libraries/Microsoft.Extensions.AI.Abstractions/Microsoft.Extensions.AI.Abstractions.json +++ b/src/Libraries/Microsoft.Extensions.AI.Abstractions/Microsoft.Extensions.AI.Abstractions.json @@ -1503,7 +1503,7 @@ }, { "Member": "override string Microsoft.Extensions.AI.DelegatingAIFunction.ToString();", - "Stage": "Experimental" + "Stage": "Stable" } ], "Properties": [ @@ -1609,42 +1609,6 @@ } ] }, - { - "Type": "class Microsoft.Extensions.AI.DelegatingSpeechToTextClient : Microsoft.Extensions.AI.ISpeechToTextClient, System.IDisposable", - "Stage": "Experimental", - "Methods": [ - { - "Member": "Microsoft.Extensions.AI.DelegatingSpeechToTextClient.DelegatingSpeechToTextClient(Microsoft.Extensions.AI.ISpeechToTextClient innerClient);", - "Stage": "Experimental" - }, - { - "Member": "void Microsoft.Extensions.AI.DelegatingSpeechToTextClient.Dispose();", - "Stage": "Experimental" - }, - { - "Member": "virtual void Microsoft.Extensions.AI.DelegatingSpeechToTextClient.Dispose(bool disposing);", - "Stage": "Experimental" - }, - { - "Member": "virtual object? Microsoft.Extensions.AI.DelegatingSpeechToTextClient.GetService(System.Type serviceType, object? serviceKey = null);", - "Stage": "Experimental" - }, - { - "Member": "virtual System.Collections.Generic.IAsyncEnumerable Microsoft.Extensions.AI.DelegatingSpeechToTextClient.GetStreamingTextAsync(System.IO.Stream audioSpeechStream, Microsoft.Extensions.AI.SpeechToTextOptions? options = null, System.Threading.CancellationToken cancellationToken = default(System.Threading.CancellationToken));", - "Stage": "Experimental" - }, - { - "Member": "virtual System.Threading.Tasks.Task Microsoft.Extensions.AI.DelegatingSpeechToTextClient.GetTextAsync(System.IO.Stream audioSpeechStream, Microsoft.Extensions.AI.SpeechToTextOptions? options = null, System.Threading.CancellationToken cancellationToken = default(System.Threading.CancellationToken));", - "Stage": "Experimental" - } - ], - "Properties": [ - { - "Member": "Microsoft.Extensions.AI.ISpeechToTextClient Microsoft.Extensions.AI.DelegatingSpeechToTextClient.InnerClient { get; }", - "Stage": "Experimental" - } - ] - }, { "Type": "class Microsoft.Extensions.AI.Embedding", "Stage": "Stable", @@ -2085,24 +2049,6 @@ } ] }, - { - "Type": "interface Microsoft.Extensions.AI.ISpeechToTextClient : System.IDisposable", - "Stage": "Experimental", - "Methods": [ - { - "Member": "object? Microsoft.Extensions.AI.ISpeechToTextClient.GetService(System.Type serviceType, object? serviceKey = null);", - "Stage": "Experimental" - }, - { - "Member": "System.Collections.Generic.IAsyncEnumerable Microsoft.Extensions.AI.ISpeechToTextClient.GetStreamingTextAsync(System.IO.Stream audioSpeechStream, Microsoft.Extensions.AI.SpeechToTextOptions? options = null, System.Threading.CancellationToken cancellationToken = default(System.Threading.CancellationToken));", - "Stage": "Experimental" - }, - { - "Member": "System.Threading.Tasks.Task Microsoft.Extensions.AI.ISpeechToTextClient.GetTextAsync(System.IO.Stream audioSpeechStream, Microsoft.Extensions.AI.SpeechToTextOptions? options = null, System.Threading.CancellationToken cancellationToken = default(System.Threading.CancellationToken));", - "Stage": "Experimental" - } - ] - }, { "Type": "sealed class Microsoft.Extensions.AI.NoneChatToolMode : Microsoft.Extensions.AI.ChatToolMode", "Stage": "Stable", @@ -2145,304 +2091,6 @@ } ] }, - { - "Type": "static class Microsoft.Extensions.AI.SpeechToTextClientExtensions", - "Stage": "Experimental", - "Methods": [ - { - "Member": "static TService? Microsoft.Extensions.AI.SpeechToTextClientExtensions.GetService(this Microsoft.Extensions.AI.ISpeechToTextClient client, object? serviceKey = null);", - "Stage": "Experimental" - }, - { - "Member": "static System.Collections.Generic.IAsyncEnumerable Microsoft.Extensions.AI.SpeechToTextClientExtensions.GetStreamingTextAsync(this Microsoft.Extensions.AI.ISpeechToTextClient client, Microsoft.Extensions.AI.DataContent audioSpeechContent, Microsoft.Extensions.AI.SpeechToTextOptions? options = null, System.Threading.CancellationToken cancellationToken = default(System.Threading.CancellationToken));", - "Stage": "Experimental" - }, - { - "Member": "static System.Threading.Tasks.Task Microsoft.Extensions.AI.SpeechToTextClientExtensions.GetTextAsync(this Microsoft.Extensions.AI.ISpeechToTextClient client, Microsoft.Extensions.AI.DataContent audioSpeechContent, Microsoft.Extensions.AI.SpeechToTextOptions? options = null, System.Threading.CancellationToken cancellationToken = default(System.Threading.CancellationToken));", - "Stage": "Experimental" - } - ] - }, - { - "Type": "class Microsoft.Extensions.AI.SpeechToTextClientMetadata", - "Stage": "Experimental", - "Methods": [ - { - "Member": "Microsoft.Extensions.AI.SpeechToTextClientMetadata.SpeechToTextClientMetadata(string? providerName = null, System.Uri? providerUri = null, string? defaultModelId = null);", - "Stage": "Experimental" - } - ], - "Properties": [ - { - "Member": "string? Microsoft.Extensions.AI.SpeechToTextClientMetadata.DefaultModelId { get; }", - "Stage": "Experimental" - }, - { - "Member": "string? Microsoft.Extensions.AI.SpeechToTextClientMetadata.ProviderName { get; }", - "Stage": "Experimental" - }, - { - "Member": "System.Uri? Microsoft.Extensions.AI.SpeechToTextClientMetadata.ProviderUri { get; }", - "Stage": "Experimental" - } - ] - }, - { - "Type": "class Microsoft.Extensions.AI.SpeechToTextOptions", - "Stage": "Experimental", - "Methods": [ - { - "Member": "Microsoft.Extensions.AI.SpeechToTextOptions.SpeechToTextOptions();", - "Stage": "Experimental" - }, - { - "Member": "virtual Microsoft.Extensions.AI.SpeechToTextOptions Microsoft.Extensions.AI.SpeechToTextOptions.Clone();", - "Stage": "Experimental" - } - ], - "Properties": [ - { - "Member": "Microsoft.Extensions.AI.AdditionalPropertiesDictionary? Microsoft.Extensions.AI.SpeechToTextOptions.AdditionalProperties { get; set; }", - "Stage": "Experimental" - }, - { - "Member": "string? Microsoft.Extensions.AI.SpeechToTextOptions.ModelId { get; set; }", - "Stage": "Experimental" - }, - { - "Member": "System.Func? Microsoft.Extensions.AI.SpeechToTextOptions.RawRepresentationFactory { get; set; }", - "Stage": "Experimental" - }, - { - "Member": "string? Microsoft.Extensions.AI.SpeechToTextOptions.SpeechLanguage { get; set; }", - "Stage": "Experimental" - }, - { - "Member": "int? Microsoft.Extensions.AI.SpeechToTextOptions.SpeechSampleRate { get; set; }", - "Stage": "Experimental" - }, - { - "Member": "string? Microsoft.Extensions.AI.SpeechToTextOptions.TextLanguage { get; set; }", - "Stage": "Experimental" - } - ] - }, - { - "Type": "class Microsoft.Extensions.AI.SpeechToTextResponse", - "Stage": "Experimental", - "Methods": [ - { - "Member": "Microsoft.Extensions.AI.SpeechToTextResponse.SpeechToTextResponse();", - "Stage": "Experimental" - }, - { - "Member": "Microsoft.Extensions.AI.SpeechToTextResponse.SpeechToTextResponse(System.Collections.Generic.IList contents);", - "Stage": "Experimental" - }, - { - "Member": "Microsoft.Extensions.AI.SpeechToTextResponse.SpeechToTextResponse(string? content);", - "Stage": "Experimental" - }, - { - "Member": "Microsoft.Extensions.AI.SpeechToTextResponseUpdate[] Microsoft.Extensions.AI.SpeechToTextResponse.ToSpeechToTextResponseUpdates();", - "Stage": "Experimental" - }, - { - "Member": "override string Microsoft.Extensions.AI.SpeechToTextResponse.ToString();", - "Stage": "Experimental" - } - ], - "Properties": [ - { - "Member": "Microsoft.Extensions.AI.AdditionalPropertiesDictionary? Microsoft.Extensions.AI.SpeechToTextResponse.AdditionalProperties { get; set; }", - "Stage": "Experimental" - }, - { - "Member": "System.Collections.Generic.IList Microsoft.Extensions.AI.SpeechToTextResponse.Contents { get; set; }", - "Stage": "Experimental" - }, - { - "Member": "System.TimeSpan? Microsoft.Extensions.AI.SpeechToTextResponse.EndTime { get; set; }", - "Stage": "Experimental" - }, - { - "Member": "string? Microsoft.Extensions.AI.SpeechToTextResponse.ModelId { get; set; }", - "Stage": "Experimental" - }, - { - "Member": "object? Microsoft.Extensions.AI.SpeechToTextResponse.RawRepresentation { get; set; }", - "Stage": "Experimental" - }, - { - "Member": "string? Microsoft.Extensions.AI.SpeechToTextResponse.ResponseId { get; set; }", - "Stage": "Experimental" - }, - { - "Member": "System.TimeSpan? Microsoft.Extensions.AI.SpeechToTextResponse.StartTime { get; set; }", - "Stage": "Experimental" - }, - { - "Member": "string Microsoft.Extensions.AI.SpeechToTextResponse.Text { get; }", - "Stage": "Experimental" - } - ] - }, - { - "Type": "class Microsoft.Extensions.AI.SpeechToTextResponseUpdate", - "Stage": "Experimental", - "Methods": [ - { - "Member": "Microsoft.Extensions.AI.SpeechToTextResponseUpdate.SpeechToTextResponseUpdate();", - "Stage": "Experimental" - }, - { - "Member": "Microsoft.Extensions.AI.SpeechToTextResponseUpdate.SpeechToTextResponseUpdate(System.Collections.Generic.IList contents);", - "Stage": "Experimental" - }, - { - "Member": "Microsoft.Extensions.AI.SpeechToTextResponseUpdate.SpeechToTextResponseUpdate(string? content);", - "Stage": "Experimental" - }, - { - "Member": "override string Microsoft.Extensions.AI.SpeechToTextResponseUpdate.ToString();", - "Stage": "Experimental" - } - ], - "Properties": [ - { - "Member": "Microsoft.Extensions.AI.AdditionalPropertiesDictionary? Microsoft.Extensions.AI.SpeechToTextResponseUpdate.AdditionalProperties { get; set; }", - "Stage": "Experimental" - }, - { - "Member": "System.Collections.Generic.IList Microsoft.Extensions.AI.SpeechToTextResponseUpdate.Contents { get; set; }", - "Stage": "Experimental" - }, - { - "Member": "System.TimeSpan? Microsoft.Extensions.AI.SpeechToTextResponseUpdate.EndTime { get; set; }", - "Stage": "Experimental" - }, - { - "Member": "Microsoft.Extensions.AI.SpeechToTextResponseUpdateKind Microsoft.Extensions.AI.SpeechToTextResponseUpdate.Kind { get; set; }", - "Stage": "Experimental" - }, - { - "Member": "string? Microsoft.Extensions.AI.SpeechToTextResponseUpdate.ModelId { get; set; }", - "Stage": "Experimental" - }, - { - "Member": "object? Microsoft.Extensions.AI.SpeechToTextResponseUpdate.RawRepresentation { get; set; }", - "Stage": "Experimental" - }, - { - "Member": "string? Microsoft.Extensions.AI.SpeechToTextResponseUpdate.ResponseId { get; set; }", - "Stage": "Experimental" - }, - { - "Member": "System.TimeSpan? Microsoft.Extensions.AI.SpeechToTextResponseUpdate.StartTime { get; set; }", - "Stage": "Experimental" - }, - { - "Member": "string Microsoft.Extensions.AI.SpeechToTextResponseUpdate.Text { get; }", - "Stage": "Experimental" - } - ] - }, - { - "Type": "static class Microsoft.Extensions.AI.SpeechToTextResponseUpdateExtensions", - "Stage": "Experimental", - "Methods": [ - { - "Member": "static Microsoft.Extensions.AI.SpeechToTextResponse Microsoft.Extensions.AI.SpeechToTextResponseUpdateExtensions.ToSpeechToTextResponse(this System.Collections.Generic.IEnumerable updates);", - "Stage": "Experimental" - }, - { - "Member": "static System.Threading.Tasks.Task Microsoft.Extensions.AI.SpeechToTextResponseUpdateExtensions.ToSpeechToTextResponseAsync(this System.Collections.Generic.IAsyncEnumerable updates, System.Threading.CancellationToken cancellationToken = default(System.Threading.CancellationToken));", - "Stage": "Experimental" - } - ] - }, - { - "Type": "readonly struct Microsoft.Extensions.AI.SpeechToTextResponseUpdateKind : System.IEquatable", - "Stage": "Experimental", - "Methods": [ - { - "Member": "Microsoft.Extensions.AI.SpeechToTextResponseUpdateKind.SpeechToTextResponseUpdateKind(string value);", - "Stage": "Experimental" - }, - { - "Member": "Microsoft.Extensions.AI.SpeechToTextResponseUpdateKind.SpeechToTextResponseUpdateKind();", - "Stage": "Experimental" - }, - { - "Member": "override bool Microsoft.Extensions.AI.SpeechToTextResponseUpdateKind.Equals(object? obj);", - "Stage": "Experimental" - }, - { - "Member": "bool Microsoft.Extensions.AI.SpeechToTextResponseUpdateKind.Equals(Microsoft.Extensions.AI.SpeechToTextResponseUpdateKind other);", - "Stage": "Experimental" - }, - { - "Member": "override int Microsoft.Extensions.AI.SpeechToTextResponseUpdateKind.GetHashCode();", - "Stage": "Experimental" - }, - { - "Member": "static bool Microsoft.Extensions.AI.SpeechToTextResponseUpdateKind.operator ==(Microsoft.Extensions.AI.SpeechToTextResponseUpdateKind left, Microsoft.Extensions.AI.SpeechToTextResponseUpdateKind right);", - "Stage": "Experimental" - }, - { - "Member": "static bool Microsoft.Extensions.AI.SpeechToTextResponseUpdateKind.operator !=(Microsoft.Extensions.AI.SpeechToTextResponseUpdateKind left, Microsoft.Extensions.AI.SpeechToTextResponseUpdateKind right);", - "Stage": "Experimental" - }, - { - "Member": "override string Microsoft.Extensions.AI.SpeechToTextResponseUpdateKind.ToString();", - "Stage": "Experimental" - } - ], - "Properties": [ - { - "Member": "static Microsoft.Extensions.AI.SpeechToTextResponseUpdateKind Microsoft.Extensions.AI.SpeechToTextResponseUpdateKind.Error { get; }", - "Stage": "Experimental" - }, - { - "Member": "static Microsoft.Extensions.AI.SpeechToTextResponseUpdateKind Microsoft.Extensions.AI.SpeechToTextResponseUpdateKind.SessionClose { get; }", - "Stage": "Experimental" - }, - { - "Member": "static Microsoft.Extensions.AI.SpeechToTextResponseUpdateKind Microsoft.Extensions.AI.SpeechToTextResponseUpdateKind.SessionOpen { get; }", - "Stage": "Experimental" - }, - { - "Member": "static Microsoft.Extensions.AI.SpeechToTextResponseUpdateKind Microsoft.Extensions.AI.SpeechToTextResponseUpdateKind.TextUpdated { get; }", - "Stage": "Experimental" - }, - { - "Member": "static Microsoft.Extensions.AI.SpeechToTextResponseUpdateKind Microsoft.Extensions.AI.SpeechToTextResponseUpdateKind.TextUpdating { get; }", - "Stage": "Experimental" - }, - { - "Member": "string Microsoft.Extensions.AI.SpeechToTextResponseUpdateKind.Value { get; }", - "Stage": "Experimental" - } - ] - }, - { - "Type": "sealed class Microsoft.Extensions.AI.SpeechToTextResponseUpdateKind.Converter", - "Stage": "Experimental", - "Methods": [ - { - "Member": "Microsoft.Extensions.AI.SpeechToTextResponseUpdateKind.Converter.Converter();", - "Stage": "Experimental" - }, - { - "Member": "override Microsoft.Extensions.AI.SpeechToTextResponseUpdateKind Microsoft.Extensions.AI.SpeechToTextResponseUpdateKind.Converter.Read(ref System.Text.Json.Utf8JsonReader reader, System.Type typeToConvert, System.Text.Json.JsonSerializerOptions options);", - "Stage": "Experimental" - }, - { - "Member": "override void Microsoft.Extensions.AI.SpeechToTextResponseUpdateKind.Converter.Write(System.Text.Json.Utf8JsonWriter writer, Microsoft.Extensions.AI.SpeechToTextResponseUpdateKind value, System.Text.Json.JsonSerializerOptions options);", - "Stage": "Experimental" - } - ] - }, { "Type": "sealed class Microsoft.Extensions.AI.TextContent : Microsoft.Extensions.AI.AIContent", "Stage": "Stable", diff --git a/src/Libraries/Microsoft.Extensions.AI.Abstractions/Utilities/AIJsonUtilities.Schema.Create.cs b/src/Libraries/Microsoft.Extensions.AI.Abstractions/Utilities/AIJsonUtilities.Schema.Create.cs index 667b3c4d080..1fa24375079 100644 --- a/src/Libraries/Microsoft.Extensions.AI.Abstractions/Utilities/AIJsonUtilities.Schema.Create.cs +++ b/src/Libraries/Microsoft.Extensions.AI.Abstractions/Utilities/AIJsonUtilities.Schema.Create.cs @@ -188,12 +188,12 @@ public static JsonElement CreateJsonSchema( } /// Gets the default JSON schema to be used by types or functions. - internal static JsonElement DefaultJsonSchema { get; } = ParseJsonElement("{}"u8); + internal static JsonElement DefaultJsonSchema { get; } = JsonElement.Parse("{}"u8); /// Validates the provided JSON schema document. internal static void ValidateSchemaDocument(JsonElement document, [CallerArgumentExpression("document")] string? paramName = null) { - if (document.ValueKind is not JsonValueKind.Object or JsonValueKind.False or JsonValueKind.True) + if (document.ValueKind is not (JsonValueKind.Object or JsonValueKind.False or JsonValueKind.True)) { Throw.ArgumentException(paramName ?? "schema", "The schema document must be an object or a boolean value."); } @@ -750,12 +750,6 @@ private static void InsertAtStart(this JsonObject jsonObject, string key, JsonNo #endif } - private static JsonElement ParseJsonElement(ReadOnlySpan utf8Json) - { - Utf8JsonReader reader = new(utf8Json); - return JsonElement.ParseValue(ref reader); - } - /// /// Tries to get the effective default value for a parameter, checking both C# default value syntax and DefaultValueAttribute. /// diff --git a/src/Libraries/Microsoft.Extensions.AI.AzureAIInference/CHANGELOG.md b/src/Libraries/Microsoft.Extensions.AI.AzureAIInference/CHANGELOG.md index 60423003454..87854975b37 100644 --- a/src/Libraries/Microsoft.Extensions.AI.AzureAIInference/CHANGELOG.md +++ b/src/Libraries/Microsoft.Extensions.AI.AzureAIInference/CHANGELOG.md @@ -1,5 +1,9 @@ # Release History +## 10.0.0-preview.1.25560.10 + +- Updated .NET dependencies to 10.0.0 versions. + ## 9.10.1-preview.1.25521.4 - No changes. diff --git a/src/Libraries/Microsoft.Extensions.AI.OpenAI/CHANGELOG.md b/src/Libraries/Microsoft.Extensions.AI.OpenAI/CHANGELOG.md index 491624332da..a7e886aed31 100644 --- a/src/Libraries/Microsoft.Extensions.AI.OpenAI/CHANGELOG.md +++ b/src/Libraries/Microsoft.Extensions.AI.OpenAI/CHANGELOG.md @@ -1,5 +1,15 @@ # Release History +## NOT YET RELEASED + +- Updated to depend on OpenAI 2.7.0 +- Added support for image detail in OpenAI Responses `IChatClient` + +## 10.0.0-preview.1.25560.10 + +- Added support for `HostedImageGenerationTool` in the OpenAI Responses `IChatClient`. +- Updated .NET dependencies to 10.0.0 versions. + ## 9.10.2-preview.1.25552.1 - Updated to depend on OpenAI 2.6.0. diff --git a/src/Libraries/Microsoft.Extensions.AI.OpenAI/MicrosoftExtensionsAIChatExtensions.cs b/src/Libraries/Microsoft.Extensions.AI.OpenAI/MicrosoftExtensionsAIChatExtensions.cs index acdc42be3e0..40009005cb6 100644 --- a/src/Libraries/Microsoft.Extensions.AI.OpenAI/MicrosoftExtensionsAIChatExtensions.cs +++ b/src/Libraries/Microsoft.Extensions.AI.OpenAI/MicrosoftExtensionsAIChatExtensions.cs @@ -234,7 +234,7 @@ static object ToToolResult(ChatMessageContent content) part.Write(writer, ModelReaderWriterOptions.Json); } - return JsonSerializer.Deserialize(ms.GetBuffer().AsSpan(0, (int)ms.Position), AIJsonUtilities.DefaultOptions.GetTypeInfo(typeof(JsonElement)))!; + return JsonElement.Parse(ms.GetBuffer().AsSpan(0, (int)ms.Position)); } break; diff --git a/src/Libraries/Microsoft.Extensions.AI.OpenAI/OpenAIEmbeddingGenerator.cs b/src/Libraries/Microsoft.Extensions.AI.OpenAI/OpenAIEmbeddingGenerator.cs index d0e1276462f..b0a46ba19c8 100644 --- a/src/Libraries/Microsoft.Extensions.AI.OpenAI/OpenAIEmbeddingGenerator.cs +++ b/src/Libraries/Microsoft.Extensions.AI.OpenAI/OpenAIEmbeddingGenerator.cs @@ -68,6 +68,14 @@ public async Task>> GenerateAsync(IEnumerab _embeddingClient.GenerateEmbeddingsAsync(values, openAIOptions, cancellationToken); var embeddings = (await t.ConfigureAwait(false)).Value; + UsageDetails? usage = embeddings.Usage is not null ? + new() + { + InputTokenCount = embeddings.Usage.InputTokenCount, + TotalTokenCount = embeddings.Usage.TotalTokenCount + } : + null; + return new(embeddings.Select(e => new Embedding(e.ToFloats()) { @@ -75,11 +83,7 @@ public async Task>> GenerateAsync(IEnumerab ModelId = embeddings.Model, })) { - Usage = new() - { - InputTokenCount = embeddings.Usage.InputTokenCount, - TotalTokenCount = embeddings.Usage.TotalTokenCount - }, + Usage = usage, }; } diff --git a/src/Libraries/Microsoft.Extensions.AI.OpenAI/OpenAIResponsesChatClient.cs b/src/Libraries/Microsoft.Extensions.AI.OpenAI/OpenAIResponsesChatClient.cs index 6913e999936..d14c0036358 100644 --- a/src/Libraries/Microsoft.Extensions.AI.OpenAI/OpenAIResponsesChatClient.cs +++ b/src/Libraries/Microsoft.Extensions.AI.OpenAI/OpenAIResponsesChatClient.cs @@ -5,7 +5,6 @@ using System.ClientModel; using System.ClientModel.Primitives; using System.Collections.Generic; -using System.Diagnostics.CodeAnalysis; using System.Linq; using System.Reflection; using System.Runtime.CompilerServices; @@ -27,11 +26,6 @@ namespace Microsoft.Extensions.AI; /// Represents an for an . internal sealed class OpenAIResponsesChatClient : IChatClient { - // Fix this to not use reflection once https://github.com/openai/openai-dotnet/issues/643 is addressed. - [DynamicallyAccessedMembers(DynamicallyAccessedMemberTypes.PublicProperties)] - private static readonly Type? _internalResponseReasoningSummaryTextDeltaEventType = Type.GetType("OpenAI.Responses.InternalResponseReasoningSummaryTextDeltaEvent, OpenAI"); - private static readonly PropertyInfo? _summaryTextDeltaProperty = _internalResponseReasoningSummaryTextDeltaEventType?.GetProperty("Delta"); - // These delegate instances are used to call the internal overloads of CreateResponseAsync and CreateResponseStreamingAsync that accept // a RequestOptions. These should be replaced once a better way to pass RequestOptions is available. private static readonly Func, ResponseCreationOptions, RequestOptions, Task>>? @@ -393,6 +387,14 @@ ChatResponseUpdate CreateUpdate(AIContent? content = null) => yield return CreateUpdate(new TextContent(outputTextDeltaUpdate.Delta)); break; + case StreamingResponseReasoningSummaryTextDeltaUpdate reasoningSummaryTextDeltaUpdate: + yield return CreateUpdate(new TextReasoningContent(reasoningSummaryTextDeltaUpdate.Delta)); + break; + + case StreamingResponseReasoningTextDeltaUpdate reasoningTextDeltaUpdate: + yield return CreateUpdate(new TextReasoningContent(reasoningTextDeltaUpdate.Delta)); + break; + case StreamingResponseOutputItemDoneUpdate outputItemDoneUpdate when outputItemDoneUpdate.Item is FunctionCallResponseItem fcri: yield return CreateUpdate(OpenAIClientExtensions.ParseCallContent(fcri.FunctionArguments.ToString(), fcri.CallId, fcri.FunctionName)); break; @@ -452,19 +454,11 @@ outputItemDoneUpdate.Item is MessageResponseItem mri && }); break; - // Replace with public StreamingResponseReasoningSummaryTextDelta when available - case StreamingResponseUpdate when - streamingUpdate.GetType() == _internalResponseReasoningSummaryTextDeltaEventType && - _summaryTextDeltaProperty?.GetValue(streamingUpdate) is string delta: - yield return CreateUpdate(new TextReasoningContent(delta)); - break; - case StreamingResponseImageGenerationCallInProgressUpdate imageGenInProgress: yield return CreateUpdate(new ImageGenerationToolCallContent { ImageId = imageGenInProgress.ItemId, RawRepresentation = imageGenInProgress, - }); goto default; @@ -851,11 +845,11 @@ internal static IEnumerable ToOpenAIResponseItems(IEnumerable().FirstOrDefault(); var outputType = imageGenTool?.OutputFileFormat?.ToString() ?? "png"; - var bytes = update.PartialImageBytes; - - if (bytes is null || bytes.Length == 0) - { - // workaround https://github.com/openai/openai-dotnet/issues/809 - if (update.Patch.TryGetJson("$.partial_image_b64"u8, out var jsonBytes)) - { - Utf8JsonReader reader = new(jsonBytes.Span); - _ = reader.Read(); - bytes = BinaryData.FromBytes(reader.GetBytesFromBase64()); - } - } - return new ImageGenerationToolResultContent { ImageId = update.ItemId, RawRepresentation = update, Outputs = new List { - new DataContent(bytes, $"image/{outputType}") + new DataContent(update.PartialImageBytes, $"image/{outputType}") { AdditionalProperties = new() { @@ -1385,6 +1367,21 @@ private static ImageGenerationToolResultContent GetImageGenerationResult(Streami return null; } + private static ResponseImageDetailLevel? GetImageDetail(AIContent content) + { + if (content.AdditionalProperties?.TryGetValue("detail", out object? value) is true) + { + return value switch + { + string detailString => new ResponseImageDetailLevel(detailString), + ResponseImageDetailLevel detail => detail, + _ => null + }; + } + + return null; + } + /// Provides an wrapper for a . internal sealed class ResponseToolAITool(ResponseTool tool) : AITool { diff --git a/src/Libraries/Microsoft.Extensions.AI.OpenAI/OpenAIResponsesContinuationToken.cs b/src/Libraries/Microsoft.Extensions.AI.OpenAI/OpenAIResponsesContinuationToken.cs index 229f8b40f69..8e6f5ffd71c 100644 --- a/src/Libraries/Microsoft.Extensions.AI.OpenAI/OpenAIResponsesContinuationToken.cs +++ b/src/Libraries/Microsoft.Extensions.AI.OpenAI/OpenAIResponsesContinuationToken.cs @@ -53,19 +53,14 @@ public override ReadOnlyMemory ToBytes() /// /// The token to create the from. /// A equivalent of the provided . - internal static OpenAIResponsesContinuationToken FromToken(object token) + internal static OpenAIResponsesContinuationToken FromToken(ResponseContinuationToken token) { if (token is OpenAIResponsesContinuationToken openAIResponsesContinuationToken) { return openAIResponsesContinuationToken; } - if (token is not ResponseContinuationToken) - { - Throw.ArgumentException(nameof(token), "Failed to create OpenAIResponsesResumptionToken from provided token because it is not of type ResponseContinuationToken."); - } - - ReadOnlyMemory data = ((ResponseContinuationToken)token).ToBytes(); + ReadOnlyMemory data = token.ToBytes(); if (data.Length == 0) { diff --git a/src/Libraries/Microsoft.Extensions.AI/CHANGELOG.md b/src/Libraries/Microsoft.Extensions.AI/CHANGELOG.md index f3c53f0d8a1..39efc546daa 100644 --- a/src/Libraries/Microsoft.Extensions.AI/CHANGELOG.md +++ b/src/Libraries/Microsoft.Extensions.AI/CHANGELOG.md @@ -1,5 +1,10 @@ # Release History +## 10.0.0 + +- Added experimental `ImageGenerationChatClient`. +- Updated .NET dependencies to 10.0.0 versions. + ## 9.10.2 - Updated the Open Telemetry instrumentation to conform to the latest 1.38 draft specification of the Semantic Conventions for Generative AI systems. diff --git a/src/Libraries/Microsoft.Extensions.DataIngestion.MarkItDown/MarkItDownMcpReader.cs b/src/Libraries/Microsoft.Extensions.DataIngestion.MarkItDown/MarkItDownMcpReader.cs index b75fc2e7f50..e6a14bfbf17 100644 --- a/src/Libraries/Microsoft.Extensions.DataIngestion.MarkItDown/MarkItDownMcpReader.cs +++ b/src/Libraries/Microsoft.Extensions.DataIngestion.MarkItDown/MarkItDownMcpReader.cs @@ -6,6 +6,7 @@ using System.IO; using System.Threading; using System.Threading.Tasks; +using Microsoft.Extensions.AI; using Microsoft.Shared.Diagnostics; using ModelContextProtocol.Client; using ModelContextProtocol.Protocol; @@ -42,21 +43,23 @@ public override async Task ReadAsync(FileInfo source, string throw new FileNotFoundException("The specified file does not exist.", source.FullName); } - // Read file content as base64 data URI + // Read file content and create DataContent #if NET - byte[] fileBytes = await File.ReadAllBytesAsync(source.FullName, cancellationToken).ConfigureAwait(false); + ReadOnlyMemory fileBytes = await File.ReadAllBytesAsync(source.FullName, cancellationToken).ConfigureAwait(false); #else - byte[] fileBytes; + ReadOnlyMemory fileBytes; using (FileStream fs = new(source.FullName, FileMode.Open, FileAccess.Read, FileShare.Read, 1, FileOptions.Asynchronous)) { - using MemoryStream ms = new(); + using MemoryStream ms = new((int)Math.Min(int.MaxValue, fs.Length)); await fs.CopyToAsync(ms).ConfigureAwait(false); - fileBytes = ms.ToArray(); + fileBytes = ms.GetBuffer().AsMemory(0, (int)ms.Length); } #endif - string dataUri = CreateDataUri(fileBytes, mediaType); + DataContent dataContent = new( + fileBytes, + string.IsNullOrEmpty(mediaType) ? "application/octet-stream" : mediaType!); - string markdown = await ConvertToMarkdownAsync(dataUri, cancellationToken).ConfigureAwait(false); + string markdown = await ConvertToMarkdownAsync(dataContent, cancellationToken).ConfigureAwait(false); return MarkdownParser.Parse(markdown, identifier); } @@ -67,31 +70,23 @@ public override async Task ReadAsync(Stream source, string id _ = Throw.IfNull(source); _ = Throw.IfNullOrEmpty(identifier); - // Read stream content as base64 data URI - using MemoryStream ms = new(); + // Read stream content and create DataContent + using MemoryStream ms = source.CanSeek ? new((int)Math.Min(int.MaxValue, source.Length)) : new(); #if NET await source.CopyToAsync(ms, cancellationToken).ConfigureAwait(false); #else await source.CopyToAsync(ms).ConfigureAwait(false); #endif - byte[] fileBytes = ms.ToArray(); - string dataUri = CreateDataUri(fileBytes, mediaType); + DataContent dataContent = new( + ms.GetBuffer().AsMemory(0, (int)ms.Length), + string.IsNullOrEmpty(mediaType) ? "application/octet-stream" : mediaType); - string markdown = await ConvertToMarkdownAsync(dataUri, cancellationToken).ConfigureAwait(false); + string markdown = await ConvertToMarkdownAsync(dataContent, cancellationToken).ConfigureAwait(false); return MarkdownParser.Parse(markdown, identifier); } -#pragma warning disable S3995 // URI return values should not be strings - private static string CreateDataUri(byte[] fileBytes, string? mediaType) -#pragma warning restore S3995 // URI return values should not be strings - { - string base64Content = Convert.ToBase64String(fileBytes); - string mimeType = string.IsNullOrEmpty(mediaType) ? "application/octet-stream" : mediaType!; - return $"data:{mimeType};base64,{base64Content}"; - } - - private async Task ConvertToMarkdownAsync(string dataUri, CancellationToken cancellationToken) + private async Task ConvertToMarkdownAsync(DataContent dataContent, CancellationToken cancellationToken) { // Create HTTP client transport for MCP HttpClientTransport transport = new(new HttpClientTransportOptions @@ -109,7 +104,7 @@ private async Task ConvertToMarkdownAsync(string dataUri, CancellationTo // Build parameters for convert_to_markdown tool Dictionary parameters = new() { - ["uri"] = dataUri + ["uri"] = dataContent.Uri }; // Call the convert_to_markdown tool diff --git a/src/Libraries/Microsoft.Extensions.DataIngestion/Chunkers/SectionChunker.cs b/src/Libraries/Microsoft.Extensions.DataIngestion/Chunkers/SectionChunker.cs new file mode 100644 index 00000000000..c584ece12c4 --- /dev/null +++ b/src/Libraries/Microsoft.Extensions.DataIngestion/Chunkers/SectionChunker.cs @@ -0,0 +1,87 @@ +// Licensed to the .NET Foundation under one or more agreements. +// The .NET Foundation licenses this file to you under the MIT license. + +using System; +using System.Collections.Generic; +using System.Runtime.CompilerServices; +using System.Threading; +using Microsoft.Shared.Diagnostics; + +namespace Microsoft.Extensions.DataIngestion.Chunkers; + +/// +/// Treats each in a as a separate entity. +/// +public sealed class SectionChunker : IngestionChunker +{ + private readonly ElementsChunker _elementsChunker; + + /// + /// Initializes a new instance of the class. + /// + /// The options for the chunker. + public SectionChunker(IngestionChunkerOptions options) + { + _elementsChunker = new(options); + } + + /// + public override async IAsyncEnumerable> ProcessAsync(IngestionDocument document, [EnumeratorCancellation] CancellationToken cancellationToken = default) + { + _ = Throw.IfNull(document); + + List> chunks = []; + foreach (IngestionDocumentSection section in document.Sections) + { + cancellationToken.ThrowIfCancellationRequested(); + + Process(document, section, chunks); + foreach (var chunk in chunks) + { + yield return chunk; + } + chunks.Clear(); + } + } + + private void Process(IngestionDocument document, IngestionDocumentSection section, List> chunks, string? parentContext = null) + { + List elements = new(section.Elements.Count); + string context = parentContext ?? string.Empty; + + for (int i = 0; i < section.Elements.Count; i++) + { + switch (section.Elements[i]) + { + // If the first element is a header, we use it as a context. + // This is common for various documents and readers. + case IngestionDocumentHeader documentHeader when i == 0: + context = string.IsNullOrEmpty(context) + ? documentHeader.GetMarkdown() + : context + $" {documentHeader.GetMarkdown()}"; + break; + case IngestionDocumentSection nestedSection: + Commit(); + Process(document, nestedSection, chunks, context); + break; + default: + elements.Add(section.Elements[i]); + break; + } + } + + Commit(); + + void Commit() + { + if (elements.Count > 0) + { + foreach (var chunk in _elementsChunker.Process(document, context, elements)) + { + chunks.Add(chunk); + } + elements.Clear(); + } + } + } +} diff --git a/src/Libraries/Microsoft.Extensions.DataIngestion/Microsoft.Extensions.DataIngestion.csproj b/src/Libraries/Microsoft.Extensions.DataIngestion/Microsoft.Extensions.DataIngestion.csproj index b7515183a86..8df401df7fd 100644 --- a/src/Libraries/Microsoft.Extensions.DataIngestion/Microsoft.Extensions.DataIngestion.csproj +++ b/src/Libraries/Microsoft.Extensions.DataIngestion/Microsoft.Extensions.DataIngestion.csproj @@ -28,4 +28,8 @@ + + + + diff --git a/src/Libraries/Microsoft.Extensions.DataIngestion/Utils/Batching.cs b/src/Libraries/Microsoft.Extensions.DataIngestion/Utils/Batching.cs index b210019401b..a3ec04ab088 100644 --- a/src/Libraries/Microsoft.Extensions.DataIngestion/Utils/Batching.cs +++ b/src/Libraries/Microsoft.Extensions.DataIngestion/Utils/Batching.cs @@ -3,9 +3,7 @@ using System; using System.Collections.Generic; -#if NET10_0_OR_GREATER using System.Linq; -#endif using System.Runtime.CompilerServices; using System.Threading; using System.Threading.Tasks; @@ -69,40 +67,4 @@ internal static async IAsyncEnumerable> ProcessAsync Chunk(this IAsyncEnumerable source, int count) -#pragma warning restore VSTHRD200 // Use "Async" suffix for async methods - { - _ = Throw.IfNull(source); - _ = Throw.IfLessThanOrEqual(count, 0); - - return CoreAsync(source, count); - - static async IAsyncEnumerable CoreAsync(IAsyncEnumerable source, int count, - [EnumeratorCancellation] CancellationToken cancellationToken = default) - { - var buffer = new TSource[count]; - int index = 0; - - await foreach (var item in source.WithCancellation(cancellationToken).ConfigureAwait(false)) - { - buffer[index++] = item; - - if (index == count) - { - index = 0; - yield return buffer; - } - } - - if (index > 0) - { - Array.Resize(ref buffer, index); - yield return buffer; - } - } - } -#endif } diff --git a/src/ProjectTemplates/GeneratedContent.targets b/src/ProjectTemplates/GeneratedContent.targets index 9014b892d98..388738d16c6 100644 --- a/src/ProjectTemplates/GeneratedContent.targets +++ b/src/ProjectTemplates/GeneratedContent.targets @@ -25,36 +25,47 @@ - + + + + + 10.0.0 + - 1.0.0-preview.251110.2 - 1.0.0-alpha.251110.2 - 9.5.1 - 9.5.1-preview.1.25502.11 - 1.0.0 - 1.17.0 + 1.0.0-preview.251114.1 + 1.0.0-alpha.251114.1 + 13.0.0 + 13.0.0-preview.1.25560.3 + 1.1.0 + 1.17.1 11.7.0 - 9.8.1-beta.413 - 10.0.0-rc.2.25502.107 - 9.5.1 - 2.0.0-preview.25503.2 + 13.0.0-beta.444 + 10.0.0 + 10.0.0 + 2.0.0 1.67.1 1.67.1-preview - 0.4.0-preview.1 - 5.4.8 - 1.13.0 - 0.1.11 - 6.0.3 + 0.4.0-preview.3 + 5.4.11 + 1.14.0 + 0.1.12 + 10.0.0 @@ -75,6 +86,7 @@ TemplatePackageVersion_AzureSearchDocuments=$(TemplatePackageVersion_AzureSearchDocuments); TemplatePackageVersion_CommunityToolkitAspire=$(TemplatePackageVersion_CommunityToolkitAspire); TemplatePackageVersion_MicrosoftExtensionsHosting=$(TemplatePackageVersion_MicrosoftExtensionsHosting); + TemplatePackageVersion_MicrosoftExtensionsHttpResilience=$(TemplatePackageVersion_MicrosoftExtensionsHttpResilience); TemplatePackageVersion_MicrosoftExtensionsServiceDiscovery=$(TemplatePackageVersion_MicrosoftExtensionsServiceDiscovery); TemplatePackageVersion_MicrosoftMLTokenizers=$(TemplatePackageVersion_MicrosoftMLTokenizers); TemplatePackageVersion_MicrosoftSemanticKernel=$(TemplatePackageVersion_MicrosoftSemanticKernel); @@ -83,7 +95,7 @@ TemplatePackageVersion_OllamaSharp=$(TemplatePackageVersion_OllamaSharp); TemplatePackageVersion_OpenTelemetry=$(TemplatePackageVersion_OpenTelemetry); TemplatePackageVersion_PdfPig=$(TemplatePackageVersion_PdfPig); - TemplatePackageVersion_SystemLinqAsync=$(TemplatePackageVersion_SystemLinqAsync); + TemplatePackageVersion_SystemLinqAsyncEnumerable=$(TemplatePackageVersion_SystemLinqAsyncEnumerable); LocalChatTemplateVariant=$(_LocalChatTemplateVariant); diff --git a/src/ProjectTemplates/Microsoft.Extensions.AI.Templates/src/ChatWithCustomData/ChatWithCustomData-CSharp.Web/ChatWithCustomData-CSharp.Web.csproj.in b/src/ProjectTemplates/Microsoft.Extensions.AI.Templates/src/ChatWithCustomData/ChatWithCustomData-CSharp.Web/ChatWithCustomData-CSharp.Web.csproj.in index 9368b96356f..d10c4cafd7e 100644 --- a/src/ProjectTemplates/Microsoft.Extensions.AI.Templates/src/ChatWithCustomData/ChatWithCustomData-CSharp.Web/ChatWithCustomData-CSharp.Web.csproj.in +++ b/src/ProjectTemplates/Microsoft.Extensions.AI.Templates/src/ChatWithCustomData/ChatWithCustomData-CSharp.Web/ChatWithCustomData-CSharp.Web.csproj.in @@ -40,7 +40,7 @@ - +