Thanks to visit codestin.com
Credit goes to github.com

Skip to content

Commit 67e2a60

Browse files
Merge branch 'main' into function-return-schema
2 parents 586721c + c8d2c9b commit 67e2a60

File tree

14 files changed

+281
-79
lines changed

14 files changed

+281
-79
lines changed

eng/Version.Details.xml

Lines changed: 6 additions & 6 deletions
Original file line numberDiff line numberDiff line change
@@ -194,17 +194,17 @@
194194
</Dependency>
195195
</ProductDependencies>
196196
<ToolsetDependencies>
197-
<Dependency Name="Microsoft.DotNet.Arcade.Sdk" Version="9.0.0-beta.25225.6">
197+
<Dependency Name="Microsoft.DotNet.Arcade.Sdk" Version="9.0.0-beta.25263.5">
198198
<Uri>https://github.com/dotnet/arcade</Uri>
199-
<Sha>bfbc858ba868b60fffaf7b2150f1d2165b01e786</Sha>
199+
<Sha>93823d49ca01742464ad1c0b49ea940e693b1be3</Sha>
200200
</Dependency>
201-
<Dependency Name="Microsoft.DotNet.Helix.Sdk" Version="9.0.0-beta.25225.6">
201+
<Dependency Name="Microsoft.DotNet.Helix.Sdk" Version="9.0.0-beta.25263.5">
202202
<Uri>https://github.com/dotnet/arcade</Uri>
203-
<Sha>bfbc858ba868b60fffaf7b2150f1d2165b01e786</Sha>
203+
<Sha>93823d49ca01742464ad1c0b49ea940e693b1be3</Sha>
204204
</Dependency>
205-
<Dependency Name="Microsoft.DotNet.Build.Tasks.Templating" Version="9.0.0-beta.25225.6">
205+
<Dependency Name="Microsoft.DotNet.Build.Tasks.Templating" Version="9.0.0-beta.25263.5">
206206
<Uri>https://github.com/dotnet/arcade</Uri>
207-
<Sha>bfbc858ba868b60fffaf7b2150f1d2165b01e786</Sha>
207+
<Sha>93823d49ca01742464ad1c0b49ea940e693b1be3</Sha>
208208
</Dependency>
209209
</ToolsetDependencies>
210210
</Dependencies>

eng/Versions.props

Lines changed: 1 addition & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -84,7 +84,7 @@
8484
<!-- Dependencies from https://github.com/dotnet/efcore -->
8585
<MicrosoftEntityFrameworkCoreSqliteVersion>9.0.4</MicrosoftEntityFrameworkCoreSqliteVersion>
8686
<!-- Dependencies from https://github.com/dotnet/arcade -->
87-
<MicrosoftDotNetBuildTasksTemplatingVersion>9.0.0-beta.25225.6</MicrosoftDotNetBuildTasksTemplatingVersion>
87+
<MicrosoftDotNetBuildTasksTemplatingVersion>9.0.0-beta.25263.5</MicrosoftDotNetBuildTasksTemplatingVersion>
8888
</PropertyGroup>
8989
<PropertyGroup Label="No longer automated Maestro dependency updates">
9090
<!-- Packages from dotnet/runtime -->

global.json

Lines changed: 4 additions & 4 deletions
Original file line numberDiff line numberDiff line change
@@ -1,9 +1,9 @@
11
{
22
"sdk": {
3-
"version": "9.0.105"
3+
"version": "9.0.106"
44
},
55
"tools": {
6-
"dotnet": "9.0.105",
6+
"dotnet": "9.0.106",
77
"runtimes": {
88
"dotnet": [
99
"8.0.0",
@@ -18,7 +18,7 @@
1818
"msbuild-sdks": {
1919
"Microsoft.Build.NoTargets": "3.7.0",
2020
"Microsoft.Build.Traversal": "3.2.0",
21-
"Microsoft.DotNet.Arcade.Sdk": "9.0.0-beta.25225.6",
22-
"Microsoft.DotNet.Helix.Sdk": "9.0.0-beta.25225.6"
21+
"Microsoft.DotNet.Arcade.Sdk": "9.0.0-beta.25263.5",
22+
"Microsoft.DotNet.Helix.Sdk": "9.0.0-beta.25263.5"
2323
}
2424
}

src/Libraries/Microsoft.Extensions.AI.Abstractions/Utilities/AIJsonSchemaCreateOptions.cs

Lines changed: 0 additions & 21 deletions
Original file line numberDiff line numberDiff line change
@@ -42,29 +42,8 @@ public sealed record class AIJsonSchemaCreateOptions
4242
/// </summary>
4343
public AIJsonSchemaTransformOptions? TransformOptions { get; init; }
4444

45-
/// <summary>
46-
/// Gets a value indicating whether to include the type keyword in created schemas for .NET enums.
47-
/// </summary>
48-
[Obsolete("This property has been deprecated.")]
49-
[System.ComponentModel.EditorBrowsable(System.ComponentModel.EditorBrowsableState.Never)]
50-
public bool IncludeTypeInEnumSchemas { get; init; } = true;
51-
52-
/// <summary>
53-
/// Gets a value indicating whether to generate schemas with the additionalProperties set to false for .NET objects.
54-
/// </summary>
55-
[Obsolete("This property has been deprecated. Use the equivalent property in TransformOptions instead.")]
56-
[System.ComponentModel.EditorBrowsable(System.ComponentModel.EditorBrowsableState.Never)]
57-
public bool DisallowAdditionalProperties { get; init; }
58-
5945
/// <summary>
6046
/// Gets a value indicating whether to include the $schema keyword in created schemas.
6147
/// </summary>
6248
public bool IncludeSchemaKeyword { get; init; }
63-
64-
/// <summary>
65-
/// Gets a value indicating whether to mark all properties as required in the schema.
66-
/// </summary>
67-
[Obsolete("This property has been deprecated. Use the equivalent property in TransformOptions instead.")]
68-
[System.ComponentModel.EditorBrowsable(System.ComponentModel.EditorBrowsableState.Never)]
69-
public bool RequireAllProperties { get; init; }
7049
}

src/Libraries/Microsoft.Extensions.AI.Abstractions/Utilities/AIJsonUtilities.Schema.Create.cs

Lines changed: 6 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -274,6 +274,12 @@ JsonNode TransformSchemaNode(JsonSchemaExporterContext schemaExporterContext, Js
274274
objSchema.InsertAtStart(TypePropertyName, "string");
275275
}
276276

277+
// Include the type keyword in nullable enum types
278+
if (Nullable.GetUnderlyingType(ctx.TypeInfo.Type)?.IsEnum is true && objSchema.ContainsKey(EnumPropertyName) && !objSchema.ContainsKey(TypePropertyName))
279+
{
280+
objSchema.InsertAtStart(TypePropertyName, new JsonArray { (JsonNode)"string", (JsonNode)"null" });
281+
}
282+
277283
// Filter potentially disallowed keywords.
278284
foreach (string keyword in _schemaKeywordsDisallowedByAIVendors)
279285
{

src/Libraries/Microsoft.Extensions.AI.AzureAIInference/AzureAIInferenceEmbeddingGenerator.cs

Lines changed: 14 additions & 8 deletions
Original file line numberDiff line numberDiff line change
@@ -164,17 +164,23 @@ static void ThrowInvalidData() =>
164164
}
165165

166166
/// <summary>Converts an extensions options instance to an Azure.AI.Inference options instance.</summary>
167-
/// <remarks>
168-
/// Note: we can't currently use RawRepresentationFactory due to https://github.com/Azure/azure-sdk-for-net/issues/50018.
169-
/// </remarks>
170167
private EmbeddingsOptions ToAzureAIOptions(IEnumerable<string> inputs, EmbeddingGenerationOptions? options)
171168
{
172-
EmbeddingsOptions result = new(inputs)
169+
if (options?.RawRepresentationFactory?.Invoke(this) is not EmbeddingsOptions result)
173170
{
174-
Dimensions = options?.Dimensions ?? _dimensions,
175-
Model = options?.ModelId ?? _metadata.DefaultModelId,
176-
EncodingFormat = EmbeddingEncodingFormat.Base64,
177-
};
171+
result = new EmbeddingsOptions(inputs);
172+
}
173+
else
174+
{
175+
foreach (var input in inputs)
176+
{
177+
result.Input.Add(input);
178+
}
179+
}
180+
181+
result.Dimensions ??= options?.Dimensions ?? _dimensions;
182+
result.Model ??= options?.ModelId ?? _metadata.DefaultModelId;
183+
result.EncodingFormat = EmbeddingEncodingFormat.Base64;
178184

179185
if (options?.AdditionalProperties is { } props)
180186
{

src/Libraries/Microsoft.Extensions.AI.AzureAIInference/AzureAIInferenceImageEmbeddingGenerator.cs

Lines changed: 15 additions & 8 deletions
Original file line numberDiff line numberDiff line change
@@ -117,17 +117,24 @@ void IDisposable.Dispose()
117117
}
118118

119119
/// <summary>Converts an extensions options instance to an Azure.AI.Inference options instance.</summary>
120-
/// <remarks>
121-
/// Note: we can't currently use RawRepresentationFactory due to https://github.com/Azure/azure-sdk-for-net/issues/50018.
122-
/// </remarks>
123120
private ImageEmbeddingsOptions ToAzureAIOptions(IEnumerable<DataContent> inputs, EmbeddingGenerationOptions? options)
124121
{
125-
ImageEmbeddingsOptions result = new(inputs.Select(dc => new ImageEmbeddingInput(dc.Uri)))
122+
IEnumerable<ImageEmbeddingInput> imageEmbeddingInputs = inputs.Select(dc => new ImageEmbeddingInput(dc.Uri));
123+
if (options?.RawRepresentationFactory?.Invoke(this) is not ImageEmbeddingsOptions result)
126124
{
127-
Dimensions = options?.Dimensions ?? _dimensions,
128-
Model = options?.ModelId ?? _metadata.DefaultModelId,
129-
EncodingFormat = EmbeddingEncodingFormat.Base64,
130-
};
125+
result = new ImageEmbeddingsOptions(imageEmbeddingInputs);
126+
}
127+
else
128+
{
129+
foreach (var input in imageEmbeddingInputs)
130+
{
131+
result.Input.Add(input);
132+
}
133+
}
134+
135+
result.Dimensions ??= options?.Dimensions ?? _dimensions;
136+
result.Model ??= options?.ModelId ?? _metadata.DefaultModelId;
137+
result.EncodingFormat = EmbeddingEncodingFormat.Base64;
131138

132139
if (options?.AdditionalProperties is { } props)
133140
{

src/Libraries/Microsoft.Extensions.AI.Evaluation.Safety/ContentSafetyChatClient.cs

Lines changed: 23 additions & 10 deletions
Original file line numberDiff line numberDiff line change
@@ -9,6 +9,7 @@
99
using System;
1010
using System.Collections.Generic;
1111
using System.Diagnostics;
12+
using System.Diagnostics.CodeAnalysis;
1213
using System.Linq;
1314
using System.Runtime.CompilerServices;
1415
using System.Threading;
@@ -79,17 +80,15 @@ await _service.AnnotateAsync(
7980
ModelId = Moniker
8081
};
8182
}
82-
else if (_originalChatClient is not null)
83+
else
8384
{
85+
ValidateOriginalChatClientNotNull();
86+
8487
return await _originalChatClient.GetResponseAsync(
8588
messages,
8689
options,
8790
cancellationToken).ConfigureAwait(false);
8891
}
89-
else
90-
{
91-
throw new NotSupportedException();
92-
}
9392
}
9493

9594
public async IAsyncEnumerable<ChatResponseUpdate> GetStreamingResponseAsync(
@@ -114,8 +113,10 @@ await _service.AnnotateAsync(
114113
ModelId = Moniker
115114
};
116115
}
117-
else if (_originalChatClient is not null)
116+
else
118117
{
118+
ValidateOriginalChatClientNotNull();
119+
119120
await foreach (var update in
120121
_originalChatClient.GetStreamingResponseAsync(
121122
messages,
@@ -125,10 +126,6 @@ await _service.AnnotateAsync(
125126
yield return update;
126127
}
127128
}
128-
else
129-
{
130-
throw new NotSupportedException();
131-
}
132129
}
133130

134131
public object? GetService(Type serviceType, object? serviceKey = null)
@@ -171,4 +168,20 @@ private static void ValidateSingleMessage(IEnumerable<ChatMessage> messages)
171168
Throw.ArgumentException(nameof(messages), ErrorMessage);
172169
}
173170
}
171+
172+
[MethodImpl(MethodImplOptions.AggressiveInlining)] // Inline if possible.
173+
[MemberNotNull(nameof(_originalChatClient))]
174+
private void ValidateOriginalChatClientNotNull([CallerMemberName] string? callerMemberName = null)
175+
{
176+
if (_originalChatClient is null)
177+
{
178+
string errorMessage =
179+
$"""
180+
Failed to invoke '{nameof(IChatClient)}.{callerMemberName}()'.
181+
Did you forget to specify the argument value for 'originalChatClient' or 'originalChatConfiguration' when calling '{nameof(ContentSafetyServiceConfiguration)}.ToChatConfiguration()'?
182+
""";
183+
184+
Throw.ArgumentNullException(nameof(_originalChatClient), errorMessage);
185+
}
186+
}
174187
}

src/Libraries/Microsoft.Extensions.AI.Evaluation.Safety/ContentSafetyServiceConfigurationExtensions.cs

Lines changed: 34 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -48,4 +48,38 @@ public static ChatConfiguration ToChatConfiguration(
4848

4949
return new ChatConfiguration(newChatClient);
5050
}
51+
52+
/// <summary>
53+
/// Returns a <see cref="ChatConfiguration"/> that can be used to communicate with the Azure AI Foundry Evaluation
54+
/// service for performing content safety evaluations.
55+
/// </summary>
56+
/// <param name="contentSafetyServiceConfiguration">
57+
/// An object that specifies configuration parameters such as the Azure AI project that should be used, and the
58+
/// credentials that should be used, when communicating with the Azure AI Foundry Evaluation service to perform
59+
/// content safety evaluations.
60+
/// </param>
61+
/// <param name="originalChatClient">
62+
/// The original <see cref="IChatClient"/>. The returned <see cref="ChatConfiguration.ChatClient"/> will be a
63+
/// wrapper around <paramref name="originalChatClient"/> that can be used both to communicate with the AI model
64+
/// that <paramref name="originalChatClient"/> is configured to communicate with, as well as to communicate with
65+
/// the Azure AI Foundry Evaluation service.
66+
/// </param>
67+
/// <returns>
68+
/// A <see cref="ChatConfiguration"/> that can be used to communicate with the Azure AI Foundry Evaluation service
69+
/// for performing content safety evaluations.
70+
/// </returns>
71+
public static ChatConfiguration ToChatConfiguration(
72+
this ContentSafetyServiceConfiguration contentSafetyServiceConfiguration,
73+
IChatClient originalChatClient)
74+
{
75+
_ = Throw.IfNull(contentSafetyServiceConfiguration);
76+
77+
#pragma warning disable CA2000 // Dispose objects before they go out of scope.
78+
// We can't dispose newChatClient here because it is returned to the caller.
79+
80+
var newChatClient = new ContentSafetyChatClient(contentSafetyServiceConfiguration, originalChatClient);
81+
#pragma warning restore CA2000
82+
83+
return new ChatConfiguration(newChatClient);
84+
}
5185
}

src/Libraries/Microsoft.Extensions.Caching.Hybrid/Internal/DefaultHybridCache.cs

Lines changed: 21 additions & 4 deletions
Original file line numberDiff line numberDiff line change
@@ -26,9 +26,6 @@ internal sealed partial class DefaultHybridCache : HybridCache
2626
{
2727
internal const int DefaultExpirationMinutes = 5;
2828

29-
// reserve non-printable characters from keys, to prevent potential L2 abuse
30-
private static readonly char[] _keyReservedCharacters = Enumerable.Range(0, 32).Select(i => (char)i).ToArray();
31-
3229
[System.Diagnostics.CodeAnalysis.SuppressMessage("Style", "IDE0032:Use auto property", Justification = "Keep usage explicit")]
3330
private readonly IDistributedCache? _backendCache;
3431
[System.Diagnostics.CodeAnalysis.SuppressMessage("Style", "IDE0032:Use auto property", Justification = "Keep usage explicit")]
@@ -255,6 +252,26 @@ private static ValueTask<T> RunWithoutCacheAsync<TState, T>(HybridCacheEntryFlag
255252
return null;
256253
}
257254

255+
// reserve non-printable characters from keys, to prevent potential L2 abuse
256+
private static bool ContainsReservedCharacters(ReadOnlySpan<char> key)
257+
{
258+
const char MaxControlChar = (char)31;
259+
260+
#if NET8_0_OR_GREATER
261+
return key.IndexOfAnyInRange((char)0, MaxControlChar) >= 0;
262+
#else
263+
foreach (char c in key)
264+
{
265+
if (c <= MaxControlChar)
266+
{
267+
return true;
268+
}
269+
}
270+
271+
return false;
272+
#endif
273+
}
274+
258275
private bool ValidateKey(string key)
259276
{
260277
if (string.IsNullOrWhiteSpace(key))
@@ -269,7 +286,7 @@ private bool ValidateKey(string key)
269286
return false;
270287
}
271288

272-
if (key.IndexOfAny(_keyReservedCharacters) >= 0)
289+
if (ContainsReservedCharacters(key.AsSpan()))
273290
{
274291
_logger.KeyInvalidContent();
275292
return false;

0 commit comments

Comments
 (0)