-
Notifications
You must be signed in to change notification settings - Fork 763
Commit
This commit does not belong to any branch on this repository, and may belong to a fork outside of the repository.
Add an extension method for registering custom AIContent types (#5789)
* Add an extension method for registering custom AIContent types * Fix method chaining.
- Loading branch information
1 parent
b86638d
commit 309f2b7
Showing
2 changed files
with
136 additions
and
0 deletions.
There are no files selected for viewing
72 changes: 72 additions & 0 deletions
72
src/Libraries/Microsoft.Extensions.AI.Abstractions/Utilities/AIJsonUtilities.cs
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
Original file line number | Diff line number | Diff line change |
---|---|---|
@@ -0,0 +1,72 @@ | ||
// 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.Text.Json; | ||
using System.Text.Json.Serialization.Metadata; | ||
using Microsoft.Shared.Diagnostics; | ||
|
||
#pragma warning disable S1121 // Assignments should not be made from within sub-expressions | ||
|
||
namespace Microsoft.Extensions.AI; | ||
|
||
public static partial class AIJsonUtilities | ||
{ | ||
/// <summary> | ||
/// Adds a custom content type to the polymorphic configuration for <see cref="AIContent"/>. | ||
/// </summary> | ||
/// <typeparam name="TContent">The custom content type to configure.</typeparam> | ||
/// <param name="options">The options instance to configure.</param> | ||
/// <param name="typeDiscriminatorId">The type discriminator id for the content type.</param> | ||
/// <exception cref="ArgumentNullException"><paramref name="options"/> or <paramref name="typeDiscriminatorId"/> is <see langword="null"/>.</exception> | ||
/// <exception cref="ArgumentException"><typeparamref name="TContent"/> is a built-in content type.</exception> | ||
/// <exception cref="InvalidOperationException"><paramref name="options"/> is a read-only instance.</exception> | ||
public static void AddAIContentType<TContent>(this JsonSerializerOptions options, string typeDiscriminatorId) | ||
where TContent : AIContent | ||
{ | ||
_ = Throw.IfNull(options); | ||
_ = Throw.IfNull(typeDiscriminatorId); | ||
|
||
AddAIContentTypeCore(options, typeof(TContent), typeDiscriminatorId); | ||
} | ||
|
||
/// <summary> | ||
/// Adds a custom content type to the polymorphic configuration for <see cref="AIContent"/>. | ||
/// </summary> | ||
/// <param name="options">The options instance to configure.</param> | ||
/// <param name="contentType">The custom content type to configure.</param> | ||
/// <param name="typeDiscriminatorId">The type discriminator id for the content type.</param> | ||
/// <exception cref="ArgumentNullException"><paramref name="options"/>, <paramref name="contentType"/>, or <paramref name="typeDiscriminatorId"/> is <see langword="null"/>.</exception> | ||
/// <exception cref="ArgumentException"><paramref name="contentType"/> is a built-in content type or does not derived from <see cref="AIContent"/>.</exception> | ||
/// <exception cref="InvalidOperationException"><paramref name="options"/> is a read-only instance.</exception> | ||
public static void AddAIContentType(this JsonSerializerOptions options, Type contentType, string typeDiscriminatorId) | ||
{ | ||
_ = Throw.IfNull(options); | ||
_ = Throw.IfNull(contentType); | ||
_ = Throw.IfNull(typeDiscriminatorId); | ||
|
||
if (!typeof(AIContent).IsAssignableFrom(contentType)) | ||
{ | ||
Throw.ArgumentException(nameof(contentType), "The content type must derive from AIContent."); | ||
} | ||
|
||
AddAIContentTypeCore(options, contentType, typeDiscriminatorId); | ||
} | ||
|
||
private static void AddAIContentTypeCore(JsonSerializerOptions options, Type contentType, string typeDiscriminatorId) | ||
{ | ||
if (contentType.Assembly == typeof(AIContent).Assembly) | ||
{ | ||
Throw.ArgumentException(nameof(contentType), "Cannot register built-in AI content types."); | ||
} | ||
|
||
IJsonTypeInfoResolver resolver = options.TypeInfoResolver ?? DefaultOptions.TypeInfoResolver!; | ||
options.TypeInfoResolver = resolver.WithAddedModifier(typeInfo => | ||
{ | ||
if (typeInfo.Type == typeof(AIContent)) | ||
{ | ||
(typeInfo.PolymorphismOptions ??= new()).DerivedTypes.Add(new(contentType, typeDiscriminatorId)); | ||
} | ||
}); | ||
} | ||
} |
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters