From 4f660d7f4f792918ab71d2be6cf4ac7a3969fed7 Mon Sep 17 00:00:00 2001 From: HavenDV Date: Fri, 7 Jun 2024 10:44:18 +0400 Subject: [PATCH 1/9] feat: Added initial Trimming support. --- OpenAI.sln | 6 ++++ helpers/TrimmingHelper/Program.cs | 1 + helpers/TrimmingHelper/TrimmingHelper.csproj | 30 ++++++++++++++++++++ src/OpenAI.csproj | 2 +- 4 files changed, 38 insertions(+), 1 deletion(-) create mode 100644 helpers/TrimmingHelper/Program.cs create mode 100644 helpers/TrimmingHelper/TrimmingHelper.csproj diff --git a/OpenAI.sln b/OpenAI.sln index d8229da2b..e5d95fa6c 100644 --- a/OpenAI.sln +++ b/OpenAI.sln @@ -6,6 +6,8 @@ Project("{9A19103F-16F7-4668-BE54-9A1E7A4F7556}") = "OpenAI", "src\OpenAI.csproj EndProject Project("{9A19103F-16F7-4668-BE54-9A1E7A4F7556}") = "OpenAI.Examples", "examples\OpenAI.Examples.csproj", "{1F1CD1D4-9932-4B73-99D8-C252A67D4B46}" EndProject +Project("{FAE04EC0-301F-11D3-BF4B-00C04F79EFBC}") = "TrimmingHelper", "helpers\TrimmingHelper\TrimmingHelper.csproj", "{4C6C7FB5-DD4E-44A8-9CBF-D739284FDC23}" +EndProject Global GlobalSection(SolutionConfigurationPlatforms) = preSolution Debug|Any CPU = Debug|Any CPU @@ -20,6 +22,10 @@ Global {1F1CD1D4-9932-4B73-99D8-C252A67D4B46}.Debug|Any CPU.Build.0 = Debug|Any CPU {1F1CD1D4-9932-4B73-99D8-C252A67D4B46}.Release|Any CPU.ActiveCfg = Release|Any CPU {1F1CD1D4-9932-4B73-99D8-C252A67D4B46}.Release|Any CPU.Build.0 = Release|Any CPU + {4C6C7FB5-DD4E-44A8-9CBF-D739284FDC23}.Debug|Any CPU.ActiveCfg = Debug|Any CPU + {4C6C7FB5-DD4E-44A8-9CBF-D739284FDC23}.Debug|Any CPU.Build.0 = Debug|Any CPU + {4C6C7FB5-DD4E-44A8-9CBF-D739284FDC23}.Release|Any CPU.ActiveCfg = Release|Any CPU + {4C6C7FB5-DD4E-44A8-9CBF-D739284FDC23}.Release|Any CPU.Build.0 = Release|Any CPU EndGlobalSection GlobalSection(SolutionProperties) = preSolution HideSolutionNode = FALSE diff --git a/helpers/TrimmingHelper/Program.cs b/helpers/TrimmingHelper/Program.cs new file mode 100644 index 000000000..3b94c9950 --- /dev/null +++ b/helpers/TrimmingHelper/Program.cs @@ -0,0 +1 @@ +Console.WriteLine("Build, rebuild or publish this app to see trimming warnings."); \ No newline at end of file diff --git a/helpers/TrimmingHelper/TrimmingHelper.csproj b/helpers/TrimmingHelper/TrimmingHelper.csproj new file mode 100644 index 000000000..936317c87 --- /dev/null +++ b/helpers/TrimmingHelper/TrimmingHelper.csproj @@ -0,0 +1,30 @@ + + + + Exe + net8.0 + enable + + true + + + + + + + + + + + + win-x64 + osx-arm64 + + true + + + + + + + diff --git a/src/OpenAI.csproj b/src/OpenAI.csproj index 9e44e162d..26da26ad4 100644 --- a/src/OpenAI.csproj +++ b/src/OpenAI.csproj @@ -7,7 +7,7 @@ 2.0.0 beta.2 - netstandard2.0;net6.0 + netstandard2.0;net6.0;net8.0 latest From 04d479fe8cc9260f526933e40063c4f35f6b5c5d Mon Sep 17 00:00:00 2001 From: HavenDV Date: Fri, 7 Jun 2024 11:09:02 +0400 Subject: [PATCH 2/9] fix: Added DynamicallyAccessedMembers to InternalListHelpers. --- src/Custom/Common/InternalListHelpers.cs | 31 +++++++++++++++++------- 1 file changed, 22 insertions(+), 9 deletions(-) diff --git a/src/Custom/Common/InternalListHelpers.cs b/src/Custom/Common/InternalListHelpers.cs index 4537ad780..902f39902 100644 --- a/src/Custom/Common/InternalListHelpers.cs +++ b/src/Custom/Common/InternalListHelpers.cs @@ -1,5 +1,6 @@ using System.ClientModel; using System.ClientModel.Primitives; +using System.Diagnostics.CodeAnalysis; using System.Runtime.CompilerServices; using System.Threading.Tasks; @@ -10,28 +11,40 @@ internal static class InternalListHelpers internal delegate Task AsyncListResponseFunc(string continuationToken, int? pageSize); internal delegate ClientResult ListResponseFunc(string continuationToken, int? pageSize); - internal static AsyncPageableCollection CreateAsyncPageable(AsyncListResponseFunc listResponseFunc) - where U : IJsonModel, IInternalListResponse + internal static AsyncPageableCollection CreateAsyncPageable(AsyncListResponseFunc listResponseFunc) + where TInternalList : IJsonModel, IInternalListResponse { async Task> pageFunc(string continuationToken, int? pageSize) - => GetPageFromProtocol(await listResponseFunc(continuationToken, pageSize).ConfigureAwait(false)); + => GetPageFromProtocol(await listResponseFunc(continuationToken, pageSize).ConfigureAwait(false)); return PageableResultHelpers.Create((pageSize) => pageFunc(null, pageSize), pageFunc); } - internal static PageableCollection CreatePageable(ListResponseFunc listResponseFunc) - where U : IJsonModel, IInternalListResponse + internal static PageableCollection CreatePageable(ListResponseFunc listResponseFunc) + where TInternalList : IJsonModel, IInternalListResponse { ResultPage pageFunc(string continuationToken, int? pageSize) - => GetPageFromProtocol(listResponseFunc(continuationToken, pageSize)); + => GetPageFromProtocol(listResponseFunc(continuationToken, pageSize)); return PageableResultHelpers.Create((pageSize) => pageFunc(null, pageSize), pageFunc); } [MethodImpl(MethodImplOptions.AggressiveInlining)] - private static ResultPage GetPageFromProtocol(ClientResult protocolResult) - where UInternalList : IJsonModel, IInternalListResponse + private static ResultPage GetPageFromProtocol(ClientResult protocolResult) + where TInternalList : IJsonModel, IInternalListResponse { PipelineResponse response = protocolResult.GetRawResponse(); - IInternalListResponse values = ModelReaderWriter.Read(response.Content); + IInternalListResponse values = ModelReaderWriter.Read(response.Content); return ResultPage.Create(values.Data, values.HasMore ? values.LastId : null, response); } } From 56f8bbb9c03cc7d9734dac5a09f5ca6fb53fdaec Mon Sep 17 00:00:00 2001 From: HavenDV Date: Fri, 7 Jun 2024 11:37:28 +0400 Subject: [PATCH 3/9] fix: Use preview version of System.Memory.Data. --- src/Custom/Embeddings/EmbeddingClient.cs | 12 ++++++------ src/Custom/Moderations/ModerationClient.cs | 8 ++++---- src/Custom/OpenAIModelFactory.cs | 2 +- src/OpenAI.csproj | 2 +- src/SourceGenerationContext.cs | 12 ++++++++++++ 5 files changed, 24 insertions(+), 12 deletions(-) create mode 100644 src/SourceGenerationContext.cs diff --git a/src/Custom/Embeddings/EmbeddingClient.cs b/src/Custom/Embeddings/EmbeddingClient.cs index f4c47b989..0e38cc6ab 100644 --- a/src/Custom/Embeddings/EmbeddingClient.cs +++ b/src/Custom/Embeddings/EmbeddingClient.cs @@ -81,7 +81,7 @@ public virtual async Task> GenerateEmbeddingAsync(string Argument.AssertNotNullOrEmpty(input, nameof(input)); options ??= new(); - CreateEmbeddingGenerationOptions(BinaryData.FromObjectAsJson(input), ref options); + CreateEmbeddingGenerationOptions(BinaryData.FromObjectAsJson(input, SourceGenerationContext.Default.String), ref options); using BinaryContent content = options.ToBinaryContent(); ClientResult result = await GenerateEmbeddingsAsync(content, (RequestOptions)null).ConfigureAwait(false); @@ -99,7 +99,7 @@ public virtual ClientResult GenerateEmbedding(string input, Embedding Argument.AssertNotNullOrEmpty(input, nameof(input)); options ??= new(); - CreateEmbeddingGenerationOptions(BinaryData.FromObjectAsJson(input), ref options); + CreateEmbeddingGenerationOptions(BinaryData.FromObjectAsJson(input, SourceGenerationContext.Default.String), ref options); using BinaryContent content = options.ToBinaryContent(); ClientResult result = GenerateEmbeddings(content, (RequestOptions)null); @@ -117,7 +117,7 @@ public virtual async Task> GenerateEmbeddingsA Argument.AssertNotNullOrEmpty(inputs, nameof(inputs)); options ??= new(); - CreateEmbeddingGenerationOptions(BinaryData.FromObjectAsJson(inputs), ref options); + CreateEmbeddingGenerationOptions(BinaryData.FromObjectAsJson(inputs, SourceGenerationContext.Default.IEnumerableString), ref options); using BinaryContent content = options.ToBinaryContent(); ClientResult result = await GenerateEmbeddingsAsync(content, (RequestOptions)null).ConfigureAwait(false); @@ -136,7 +136,7 @@ public virtual ClientResult GenerateEmbeddings(IEnumerable< Argument.AssertNotNullOrEmpty(inputs, nameof(inputs)); options ??= new(); - CreateEmbeddingGenerationOptions(BinaryData.FromObjectAsJson(inputs), ref options); + CreateEmbeddingGenerationOptions(BinaryData.FromObjectAsJson(inputs, SourceGenerationContext.Default.IEnumerableString), ref options); using BinaryContent content = options.ToBinaryContent(); ClientResult result = GenerateEmbeddings(content, (RequestOptions)null); @@ -154,7 +154,7 @@ public virtual async Task> GenerateEmbeddingsA Argument.AssertNotNullOrEmpty(inputs, nameof(inputs)); options ??= new(); - CreateEmbeddingGenerationOptions(BinaryData.FromObjectAsJson(inputs), ref options); + CreateEmbeddingGenerationOptions(BinaryData.FromObjectAsJson(inputs, SourceGenerationContext.Default.IEnumerableIEnumerableInt32), ref options); using BinaryContent content = options.ToBinaryContent(); ClientResult result = await GenerateEmbeddingsAsync(content, (RequestOptions)null).ConfigureAwait(false); @@ -172,7 +172,7 @@ public virtual ClientResult GenerateEmbeddings(IEnumerable< Argument.AssertNotNullOrEmpty(inputs, nameof(inputs)); options ??= new(); - CreateEmbeddingGenerationOptions(BinaryData.FromObjectAsJson(inputs), ref options); + CreateEmbeddingGenerationOptions(BinaryData.FromObjectAsJson(inputs, SourceGenerationContext.Default.IEnumerableIEnumerableInt32), ref options); using BinaryContent content = options.ToBinaryContent(); ClientResult result = GenerateEmbeddings(content, (RequestOptions)null); diff --git a/src/Custom/Moderations/ModerationClient.cs b/src/Custom/Moderations/ModerationClient.cs index bf27406fa..0fc10c6d5 100644 --- a/src/Custom/Moderations/ModerationClient.cs +++ b/src/Custom/Moderations/ModerationClient.cs @@ -74,7 +74,7 @@ public virtual async Task> ClassifyTextInputAsync Argument.AssertNotNullOrEmpty(input, nameof(input)); ModerationOptions options = new(); - CreateModerationOptions(BinaryData.FromObjectAsJson(input), ref options); + CreateModerationOptions(BinaryData.FromObjectAsJson(input, SourceGenerationContext.Default.String), ref options); using BinaryContent content = options.ToBinaryContent(); ClientResult result = await ClassifyTextInputsAsync(content, (RequestOptions)null).ConfigureAwait(false); @@ -90,7 +90,7 @@ public virtual ClientResult ClassifyTextInput(string input) Argument.AssertNotNullOrEmpty(input, nameof(input)); ModerationOptions options = new(); - CreateModerationOptions(BinaryData.FromObjectAsJson(input), ref options); + CreateModerationOptions(BinaryData.FromObjectAsJson(input, SourceGenerationContext.Default.String), ref options); using BinaryContent content = options.ToBinaryContent(); ClientResult result = ClassifyTextInputs(content, (RequestOptions)null); @@ -107,7 +107,7 @@ public virtual async Task> ClassifyTextInputs Argument.AssertNotNullOrEmpty(inputs, nameof(inputs)); ModerationOptions options = new(); - CreateModerationOptions(BinaryData.FromObjectAsJson(inputs), ref options); + CreateModerationOptions(BinaryData.FromObjectAsJson(inputs, SourceGenerationContext.Default.IEnumerableString), ref options); using BinaryContent content = options.ToBinaryContent(); ClientResult result = await ClassifyTextInputsAsync(content, (RequestOptions)null).ConfigureAwait(false); @@ -123,7 +123,7 @@ public virtual ClientResult ClassifyTextInputs(IEnumerable Argument.AssertNotNullOrEmpty(inputs, nameof(inputs)); ModerationOptions options = new(); - CreateModerationOptions(BinaryData.FromObjectAsJson(inputs), ref options); + CreateModerationOptions(BinaryData.FromObjectAsJson(inputs, SourceGenerationContext.Default.IEnumerableString), ref options); using BinaryContent content = options.ToBinaryContent(); ClientResult result = ClassifyTextInputs(content, (RequestOptions)null); diff --git a/src/Custom/OpenAIModelFactory.cs b/src/Custom/OpenAIModelFactory.cs index e5b0d4c42..f9f558ca6 100644 --- a/src/Custom/OpenAIModelFactory.cs +++ b/src/Custom/OpenAIModelFactory.cs @@ -30,7 +30,7 @@ public static EmbeddingCollection EmbeddingCollection(IEnumerable dat public static Embedding Embedding(ReadOnlyMemory vector = default, int index = default) { // TODO: Vector must be converted to base64-encoded string. - return new Embedding(index, BinaryData.FromObjectAsJson(vector), InternalEmbeddingObject.Embedding, serializedAdditionalRawData: null); + return new Embedding(index, BinaryData.FromObjectAsJson(vector, SourceGenerationContext.Default.ReadOnlyMemorySingle), InternalEmbeddingObject.Embedding, serializedAdditionalRawData: null); } } diff --git a/src/OpenAI.csproj b/src/OpenAI.csproj index 26da26ad4..dafbccbab 100644 --- a/src/OpenAI.csproj +++ b/src/OpenAI.csproj @@ -46,6 +46,6 @@ - + diff --git a/src/SourceGenerationContext.cs b/src/SourceGenerationContext.cs new file mode 100644 index 000000000..8b8e94063 --- /dev/null +++ b/src/SourceGenerationContext.cs @@ -0,0 +1,12 @@ +using System; +using System.Collections.Generic; +using System.Text.Json.Serialization; + +namespace OpenAI; + +[JsonSourceGenerationOptions] +[JsonSerializable(typeof(string))] +[JsonSerializable(typeof(IEnumerable))] +[JsonSerializable(typeof(IEnumerable>))] +[JsonSerializable(typeof(ReadOnlyMemory))] +internal sealed partial class SourceGenerationContext : JsonSerializerContext; \ No newline at end of file From 8ea3edc349604a8916cbbeb83e658857b81160a5 Mon Sep 17 00:00:00 2001 From: HavenDV Date: Sat, 8 Jun 2024 12:13:58 +0400 Subject: [PATCH 4/9] fix: Fixed dependencies feedback. --- src/OpenAI.csproj | 3 ++- 1 file changed, 2 insertions(+), 1 deletion(-) diff --git a/src/OpenAI.csproj b/src/OpenAI.csproj index dafbccbab..28cbd74fd 100644 --- a/src/OpenAI.csproj +++ b/src/OpenAI.csproj @@ -46,6 +46,7 @@ - + + From b15739b61c13211f01f070a401e8899c623fb7e9 Mon Sep 17 00:00:00 2001 From: HavenDV Date: Sat, 8 Jun 2024 12:14:48 +0400 Subject: [PATCH 5/9] refactor: Added TrimmingAttribute.cs. --- src/Custom/Common/InternalListHelpers.cs | 6 - src/Utility/Polyfill/TrimmingAttribute.cs | 421 ++++++++++++++++++++++ 2 files changed, 421 insertions(+), 6 deletions(-) create mode 100644 src/Utility/Polyfill/TrimmingAttribute.cs diff --git a/src/Custom/Common/InternalListHelpers.cs b/src/Custom/Common/InternalListHelpers.cs index 902f39902..c4d20fcdd 100644 --- a/src/Custom/Common/InternalListHelpers.cs +++ b/src/Custom/Common/InternalListHelpers.cs @@ -12,9 +12,7 @@ internal static class InternalListHelpers internal delegate ClientResult ListResponseFunc(string continuationToken, int? pageSize); internal static AsyncPageableCollection CreateAsyncPageable(AsyncListResponseFunc listResponseFunc) where TInternalList : IJsonModel, IInternalListResponse { @@ -24,9 +22,7 @@ async Task> pageFunc(string continuationToken, int? pageSize) } internal static PageableCollection CreatePageable(ListResponseFunc listResponseFunc) where TInternalList : IJsonModel, IInternalListResponse { @@ -37,9 +33,7 @@ ResultPage pageFunc(string continuationToken, int? pageSize) [MethodImpl(MethodImplOptions.AggressiveInlining)] private static ResultPage GetPageFromProtocol(ClientResult protocolResult) where TInternalList : IJsonModel, IInternalListResponse { diff --git a/src/Utility/Polyfill/TrimmingAttribute.cs b/src/Utility/Polyfill/TrimmingAttribute.cs new file mode 100644 index 000000000..3bb7a428f --- /dev/null +++ b/src/Utility/Polyfill/TrimmingAttribute.cs @@ -0,0 +1,421 @@ +// Copyright (c) Microsoft Corporation. All rights reserved. +// Licensed under the MIT License. +// From https://github.com/Azure/azure-sdk-for-net/blob/main/sdk/core/Azure.Core/src/Shared/TrimmingAttribute.cs + +#nullable enable + +namespace System.Diagnostics.CodeAnalysis; + +#if !NET7_0_OR_GREATER +/// +/// Indicates that the specified method requires the ability to generate new code at runtime, +/// for example through . +/// +/// +/// This allows tools to understand which methods are unsafe to call when compiling ahead of time. +/// +[AttributeUsage(AttributeTargets.Method | AttributeTargets.Constructor | AttributeTargets.Class, Inherited = false)] +internal sealed class RequiresDynamicCodeAttribute : Attribute +{ + /// + /// Initializes a new instance of the class + /// with the specified message. + /// + /// + /// A message that contains information about the usage of dynamic code. + /// + public RequiresDynamicCodeAttribute(string message) + { + Message = message; + } + + /// + /// Gets a message that contains information about the usage of dynamic code. + /// + public string Message { get; } + + /// + /// Gets or sets an optional URL that contains more information about the method, + /// why it requires dynamic code, and what options a consumer has to deal with it. + /// + public string? Url { get; set; } +} +#endif + +#if !NET5_0_OR_GREATER +/// +/// Indicates that the specified method requires dynamic access to code that is not referenced +/// statically, for example through . +/// +/// +/// This allows tools to understand which methods are unsafe to call when removing unreferenced +/// code from an application. +/// +[AttributeUsage(AttributeTargets.Method | AttributeTargets.Constructor | AttributeTargets.Class, Inherited = false)] +internal sealed class RequiresUnreferencedCodeAttribute : Attribute +{ + /// + /// Initializes a new instance of the class + /// with the specified message. + /// + /// + /// A message that contains information about the usage of unreferenced code. + /// + public RequiresUnreferencedCodeAttribute(string message) + { + Message = message; + } + + /// + /// Gets a message that contains information about the usage of unreferenced code. + /// + public string Message { get; } + + /// + /// Gets or sets an optional URL that contains more information about the method, + /// why it requires unreferenced code, and what options a consumer has to deal with it. + /// + public string? Url { get; set; } +} + +/// +/// Suppresses reporting of a specific rule violation, allowing multiple suppressions on a +/// single code artifact. +/// +/// +/// is different than +/// in that it doesn't have a +/// . So it is always preserved in the compiled assembly. +/// +[AttributeUsage(AttributeTargets.All, Inherited = false, AllowMultiple = true)] +internal sealed class UnconditionalSuppressMessageAttribute : Attribute +{ + /// + /// Initializes a new instance of the + /// class, specifying the category of the tool and the identifier for an analysis rule. + /// + /// The category for the attribute. + /// The identifier of the analysis rule the attribute applies to. + public UnconditionalSuppressMessageAttribute(string category, string checkId) + { + Category = category; + CheckId = checkId; + } + + /// + /// Gets the category identifying the classification of the attribute. + /// + /// + /// The property describes the tool or tool analysis category + /// for which a message suppression attribute applies. + /// + public string Category { get; } + + /// + /// Gets the identifier of the analysis tool rule to be suppressed. + /// + /// + /// Concatenated together, the and + /// properties form a unique check identifier. + /// + public string CheckId { get; } + + /// + /// Gets or sets the scope of the code that is relevant for the attribute. + /// + /// + /// The Scope property is an optional argument that specifies the metadata scope for which + /// the attribute is relevant. + /// + public string? Scope { get; set; } + + /// + /// Gets or sets a fully qualified path that represents the target of the attribute. + /// + /// + /// The property is an optional argument identifying the analysis target + /// of the attribute. An example value is "System.IO.Stream.ctor():System.Void". + /// Because it is fully qualified, it can be long, particularly for targets such as parameters. + /// The analysis tool user interface should be capable of automatically formatting the parameter. + /// + public string? Target { get; set; } + + /// + /// Gets or sets an optional argument expanding on exclusion criteria. + /// + /// + /// The property is an optional argument that specifies additional + /// exclusion where the literal metadata target is not sufficiently precise. For example, + /// the cannot be applied within a method, + /// and it may be desirable to suppress a violation against a statement in the method that will + /// give a rule violation, but not against all statements in the method. + /// + public string? MessageId { get; set; } + + /// + /// Gets or sets the justification for suppressing the code analysis message. + /// + public string? Justification { get; set; } +} + +/// +/// States a dependency that one member has on another. +/// +/// +/// This can be used to inform tooling of a dependency that is otherwise not evident purely from +/// metadata and IL, for example a member relied on via reflection. +/// +[AttributeUsage( + AttributeTargets.Constructor | AttributeTargets.Field | AttributeTargets.Method, + AllowMultiple = true, Inherited = false)] +internal sealed class DynamicDependencyAttribute : Attribute +{ + /// + /// Initializes a new instance of the class + /// with the specified signature of a member on the same type as the consumer. + /// + /// The signature of the member depended on. + public DynamicDependencyAttribute(string memberSignature) + { + MemberSignature = memberSignature; + } + + /// + /// Initializes a new instance of the class + /// with the specified signature of a member on a . + /// + /// The signature of the member depended on. + /// The containing . + public DynamicDependencyAttribute(string memberSignature, Type type) + { + MemberSignature = memberSignature; + Type = type; + } + + /// + /// Initializes a new instance of the class + /// with the specified signature of a member on a type in an assembly. + /// + /// The signature of the member depended on. + /// The full name of the type containing the specified member. + /// The assembly name of the type containing the specified member. + public DynamicDependencyAttribute(string memberSignature, string typeName, string assemblyName) + { + MemberSignature = memberSignature; + TypeName = typeName; + AssemblyName = assemblyName; + } + + /// + /// Initializes a new instance of the class + /// with the specified types of members on a . + /// + /// The types of members depended on. + /// The containing the specified members. + public DynamicDependencyAttribute(DynamicallyAccessedMemberTypes memberTypes, Type type) + { + MemberTypes = memberTypes; + Type = type; + } + + /// + /// Initializes a new instance of the class + /// with the specified types of members on a type in an assembly. + /// + /// The types of members depended on. + /// The full name of the type containing the specified members. + /// The assembly name of the type containing the specified members. + public DynamicDependencyAttribute(DynamicallyAccessedMemberTypes memberTypes, string typeName, string assemblyName) + { + MemberTypes = memberTypes; + TypeName = typeName; + AssemblyName = assemblyName; + } + + /// + /// Gets the signature of the member depended on. + /// + /// + /// Either must be a valid string or + /// must not equal , but not both. + /// + public string? MemberSignature { get; } + + /// + /// Gets the which specifies the type + /// of members depended on. + /// + /// + /// Either must be a valid string or + /// must not equal , but not both. + /// + public DynamicallyAccessedMemberTypes MemberTypes { get; } + + /// + /// Gets the containing the specified member. + /// + /// + /// If neither nor are specified, + /// the type of the consumer is assumed. + /// + public Type? Type { get; } + + /// + /// Gets the full name of the type containing the specified member. + /// + /// + /// If neither nor are specified, + /// the type of the consumer is assumed. + /// + public string? TypeName { get; } + + /// + /// Gets the assembly name of the specified type. + /// + /// + /// is only valid when is specified. + /// + public string? AssemblyName { get; } + + /// + /// Gets or sets the condition in which the dependency is applicable, e.g. "DEBUG". + /// + public string? Condition { get; set; } +} + +/// +/// Indicates that certain members on a specified are accessed dynamically, +/// for example through . +/// +/// +/// This allows tools to understand which members are being accessed during the execution +/// of a program. +/// +/// This attribute is valid on members whose type is or . +/// +/// When this attribute is applied to a location of type , the assumption is +/// that the string represents a fully qualified type name. +/// +/// When this attribute is applied to a class, interface, or struct, the members specified +/// can be accessed dynamically on instances returned from calling +/// on instances of that class, interface, or struct. +/// +/// If the attribute is applied to a method it's treated as a special case and it implies +/// the attribute should be applied to the "this" parameter of the method. As such the attribute +/// should only be used on instance methods of types assignable to System.Type (or string, but no methods +/// will use it there). +/// +[AttributeUsage( + AttributeTargets.Field | AttributeTargets.ReturnValue | AttributeTargets.GenericParameter | + AttributeTargets.Parameter | AttributeTargets.Property | AttributeTargets.Method | + AttributeTargets.Class | AttributeTargets.Interface | AttributeTargets.Struct, + Inherited = false)] +internal sealed class DynamicallyAccessedMembersAttribute : Attribute +{ + /// + /// Initializes a new instance of the class + /// with the specified member types. + /// + /// The types of members dynamically accessed. + public DynamicallyAccessedMembersAttribute(DynamicallyAccessedMemberTypes memberTypes) + { + MemberTypes = memberTypes; + } + + /// + /// Gets the which specifies the type + /// of members dynamically accessed. + /// + public DynamicallyAccessedMemberTypes MemberTypes { get; } +} + +/// +/// Specifies the types of members that are dynamically accessed. +/// +/// This enumeration has a attribute that allows a +/// bitwise combination of its member values. +/// +[Flags] +internal enum DynamicallyAccessedMemberTypes +{ + /// + /// Specifies no members. + /// + None = 0, + + /// + /// Specifies the default, parameterless public constructor. + /// + PublicParameterlessConstructor = 0x0001, + + /// + /// Specifies all public constructors. + /// + PublicConstructors = 0x0002 | PublicParameterlessConstructor, + + /// + /// Specifies all non-public constructors. + /// + NonPublicConstructors = 0x0004, + + /// + /// Specifies all public methods. + /// + PublicMethods = 0x0008, + + /// + /// Specifies all non-public methods. + /// + NonPublicMethods = 0x0010, + + /// + /// Specifies all public fields. + /// + PublicFields = 0x0020, + + /// + /// Specifies all non-public fields. + /// + NonPublicFields = 0x0040, + + /// + /// Specifies all public nested types. + /// + PublicNestedTypes = 0x0080, + + /// + /// Specifies all non-public nested types. + /// + NonPublicNestedTypes = 0x0100, + + /// + /// Specifies all public properties. + /// + PublicProperties = 0x0200, + + /// + /// Specifies all non-public properties. + /// + NonPublicProperties = 0x0400, + + /// + /// Specifies all public events. + /// + PublicEvents = 0x0800, + + /// + /// Specifies all non-public events. + /// + NonPublicEvents = 0x1000, + + /// + /// Specifies all interfaces implemented by the type. + /// + Interfaces = 0x2000, + + /// + /// Specifies all members. + /// + All = ~None +} +#endif From cfe9902849dfb7c357a94fc982d5c41b74762b91 Mon Sep 17 00:00:00 2001 From: HavenDV Date: Wed, 13 Nov 2024 12:10:46 +0400 Subject: [PATCH 6/9] fix: Fixed issues. --- helpers/TrimmingHelper/Program.cs | 1 - helpers/TrimmingHelper/TrimmingHelper.csproj | 30 ------------------- src/Custom/Embeddings/EmbeddingClient.cs | 4 +-- src/Custom/OpenAIModelFactory.cs | 2 +- .../Internal/ModelSerializationExtensions.cs | 2 +- src/OpenAI.csproj | 3 +- src/SourceGenerationContext.cs | 2 +- 7 files changed, 7 insertions(+), 37 deletions(-) delete mode 100644 helpers/TrimmingHelper/Program.cs delete mode 100644 helpers/TrimmingHelper/TrimmingHelper.csproj diff --git a/helpers/TrimmingHelper/Program.cs b/helpers/TrimmingHelper/Program.cs deleted file mode 100644 index 3b94c9950..000000000 --- a/helpers/TrimmingHelper/Program.cs +++ /dev/null @@ -1 +0,0 @@ -Console.WriteLine("Build, rebuild or publish this app to see trimming warnings."); \ No newline at end of file diff --git a/helpers/TrimmingHelper/TrimmingHelper.csproj b/helpers/TrimmingHelper/TrimmingHelper.csproj deleted file mode 100644 index 936317c87..000000000 --- a/helpers/TrimmingHelper/TrimmingHelper.csproj +++ /dev/null @@ -1,30 +0,0 @@ - - - - Exe - net8.0 - enable - - true - - - - - - - - - - - - win-x64 - osx-arm64 - - true - - - - - - - diff --git a/src/Custom/Embeddings/EmbeddingClient.cs b/src/Custom/Embeddings/EmbeddingClient.cs index 5e395282a..e74554f51 100644 --- a/src/Custom/Embeddings/EmbeddingClient.cs +++ b/src/Custom/Embeddings/EmbeddingClient.cs @@ -182,7 +182,7 @@ public virtual async Task> GenerateEmbed Argument.AssertNotNullOrEmpty(inputs, nameof(inputs)); options ??= new(); - CreateEmbeddingGenerationOptions(BinaryData.FromObjectAsJson(inputs, SourceGenerationContext.Default.IEnumerableIEnumerableInt32), ref options); + CreateEmbeddingGenerationOptions(BinaryData.FromObjectAsJson(inputs, SourceGenerationContext.Default.IEnumerableReadOnlyMemoryInt32), ref options); using BinaryContent content = options.ToBinaryContent(); ClientResult result = await GenerateEmbeddingsAsync(content, cancellationToken.ToRequestOptions()).ConfigureAwait(false); @@ -201,7 +201,7 @@ public virtual ClientResult GenerateEmbeddings(IEnume Argument.AssertNotNullOrEmpty(inputs, nameof(inputs)); options ??= new(); - CreateEmbeddingGenerationOptions(BinaryData.FromObjectAsJson(inputs, SourceGenerationContext.Default.IEnumerableIEnumerableInt32), ref options); + CreateEmbeddingGenerationOptions(BinaryData.FromObjectAsJson(inputs, SourceGenerationContext.Default.IEnumerableReadOnlyMemoryInt32), ref options); using BinaryContent content = options.ToBinaryContent(); ClientResult result = GenerateEmbeddings(content, cancellationToken.ToRequestOptions()); diff --git a/src/Custom/OpenAIModelFactory.cs b/src/Custom/OpenAIModelFactory.cs index 18d762f1e..e3aa789b1 100644 --- a/src/Custom/OpenAIModelFactory.cs +++ b/src/Custom/OpenAIModelFactory.cs @@ -30,7 +30,7 @@ public static OpenAIEmbeddingCollection OpenAIEmbeddingCollection(IEnumerable vector = default, int index = default) { // TODO: Vector must be converted to base64-encoded string. - return new OpenAIEmbedding(index, BinaryData.FromObjectAsJson(vector), InternalEmbeddingObject.Embedding, serializedAdditionalRawData: null); + return new OpenAIEmbedding(index, BinaryData.FromObjectAsJson(vector, SourceGenerationContext.Default.ReadOnlyMemorySingle), InternalEmbeddingObject.Embedding, serializedAdditionalRawData: null); } } diff --git a/src/Generated/Internal/ModelSerializationExtensions.cs b/src/Generated/Internal/ModelSerializationExtensions.cs index d1334d37b..1b4a69507 100644 --- a/src/Generated/Internal/ModelSerializationExtensions.cs +++ b/src/Generated/Internal/ModelSerializationExtensions.cs @@ -15,7 +15,7 @@ namespace OpenAI internal static class ModelSerializationExtensions { internal static readonly ModelReaderWriterOptions WireOptions = new ModelReaderWriterOptions("W"); - internal static readonly BinaryData SentinelValue = BinaryData.FromObjectAsJson("__EMPTY__"); + internal static readonly BinaryData SentinelValue = BinaryData.FromObjectAsJson("__EMPTY__", SourceGenerationContext.Default.String); public static object GetObject(this JsonElement element) { diff --git a/src/OpenAI.csproj b/src/OpenAI.csproj index 86082e2a8..4fa5cf944 100644 --- a/src/OpenAI.csproj +++ b/src/OpenAI.csproj @@ -9,7 +9,7 @@ 2.1.0 beta.2 - netstandard2.0;net6.0 + netstandard2.0;net6.0;net8.0 latest @@ -78,5 +78,6 @@ + diff --git a/src/SourceGenerationContext.cs b/src/SourceGenerationContext.cs index 8b8e94063..7b909b03e 100644 --- a/src/SourceGenerationContext.cs +++ b/src/SourceGenerationContext.cs @@ -7,6 +7,6 @@ namespace OpenAI; [JsonSourceGenerationOptions] [JsonSerializable(typeof(string))] [JsonSerializable(typeof(IEnumerable))] -[JsonSerializable(typeof(IEnumerable>))] +[JsonSerializable(typeof(IEnumerable>))] [JsonSerializable(typeof(ReadOnlyMemory))] internal sealed partial class SourceGenerationContext : JsonSerializerContext; \ No newline at end of file From 81af4aa920646ecd5513d004a7aacb8f4826d685 Mon Sep 17 00:00:00 2001 From: HavenDV Date: Wed, 13 Nov 2024 12:12:23 +0400 Subject: [PATCH 7/9] refactor: Removed Trimming attributes. --- src/Utility/Polyfill/TrimmingAttribute.cs | 421 ---------------------- 1 file changed, 421 deletions(-) delete mode 100644 src/Utility/Polyfill/TrimmingAttribute.cs diff --git a/src/Utility/Polyfill/TrimmingAttribute.cs b/src/Utility/Polyfill/TrimmingAttribute.cs deleted file mode 100644 index 3bb7a428f..000000000 --- a/src/Utility/Polyfill/TrimmingAttribute.cs +++ /dev/null @@ -1,421 +0,0 @@ -// Copyright (c) Microsoft Corporation. All rights reserved. -// Licensed under the MIT License. -// From https://github.com/Azure/azure-sdk-for-net/blob/main/sdk/core/Azure.Core/src/Shared/TrimmingAttribute.cs - -#nullable enable - -namespace System.Diagnostics.CodeAnalysis; - -#if !NET7_0_OR_GREATER -/// -/// Indicates that the specified method requires the ability to generate new code at runtime, -/// for example through . -/// -/// -/// This allows tools to understand which methods are unsafe to call when compiling ahead of time. -/// -[AttributeUsage(AttributeTargets.Method | AttributeTargets.Constructor | AttributeTargets.Class, Inherited = false)] -internal sealed class RequiresDynamicCodeAttribute : Attribute -{ - /// - /// Initializes a new instance of the class - /// with the specified message. - /// - /// - /// A message that contains information about the usage of dynamic code. - /// - public RequiresDynamicCodeAttribute(string message) - { - Message = message; - } - - /// - /// Gets a message that contains information about the usage of dynamic code. - /// - public string Message { get; } - - /// - /// Gets or sets an optional URL that contains more information about the method, - /// why it requires dynamic code, and what options a consumer has to deal with it. - /// - public string? Url { get; set; } -} -#endif - -#if !NET5_0_OR_GREATER -/// -/// Indicates that the specified method requires dynamic access to code that is not referenced -/// statically, for example through . -/// -/// -/// This allows tools to understand which methods are unsafe to call when removing unreferenced -/// code from an application. -/// -[AttributeUsage(AttributeTargets.Method | AttributeTargets.Constructor | AttributeTargets.Class, Inherited = false)] -internal sealed class RequiresUnreferencedCodeAttribute : Attribute -{ - /// - /// Initializes a new instance of the class - /// with the specified message. - /// - /// - /// A message that contains information about the usage of unreferenced code. - /// - public RequiresUnreferencedCodeAttribute(string message) - { - Message = message; - } - - /// - /// Gets a message that contains information about the usage of unreferenced code. - /// - public string Message { get; } - - /// - /// Gets or sets an optional URL that contains more information about the method, - /// why it requires unreferenced code, and what options a consumer has to deal with it. - /// - public string? Url { get; set; } -} - -/// -/// Suppresses reporting of a specific rule violation, allowing multiple suppressions on a -/// single code artifact. -/// -/// -/// is different than -/// in that it doesn't have a -/// . So it is always preserved in the compiled assembly. -/// -[AttributeUsage(AttributeTargets.All, Inherited = false, AllowMultiple = true)] -internal sealed class UnconditionalSuppressMessageAttribute : Attribute -{ - /// - /// Initializes a new instance of the - /// class, specifying the category of the tool and the identifier for an analysis rule. - /// - /// The category for the attribute. - /// The identifier of the analysis rule the attribute applies to. - public UnconditionalSuppressMessageAttribute(string category, string checkId) - { - Category = category; - CheckId = checkId; - } - - /// - /// Gets the category identifying the classification of the attribute. - /// - /// - /// The property describes the tool or tool analysis category - /// for which a message suppression attribute applies. - /// - public string Category { get; } - - /// - /// Gets the identifier of the analysis tool rule to be suppressed. - /// - /// - /// Concatenated together, the and - /// properties form a unique check identifier. - /// - public string CheckId { get; } - - /// - /// Gets or sets the scope of the code that is relevant for the attribute. - /// - /// - /// The Scope property is an optional argument that specifies the metadata scope for which - /// the attribute is relevant. - /// - public string? Scope { get; set; } - - /// - /// Gets or sets a fully qualified path that represents the target of the attribute. - /// - /// - /// The property is an optional argument identifying the analysis target - /// of the attribute. An example value is "System.IO.Stream.ctor():System.Void". - /// Because it is fully qualified, it can be long, particularly for targets such as parameters. - /// The analysis tool user interface should be capable of automatically formatting the parameter. - /// - public string? Target { get; set; } - - /// - /// Gets or sets an optional argument expanding on exclusion criteria. - /// - /// - /// The property is an optional argument that specifies additional - /// exclusion where the literal metadata target is not sufficiently precise. For example, - /// the cannot be applied within a method, - /// and it may be desirable to suppress a violation against a statement in the method that will - /// give a rule violation, but not against all statements in the method. - /// - public string? MessageId { get; set; } - - /// - /// Gets or sets the justification for suppressing the code analysis message. - /// - public string? Justification { get; set; } -} - -/// -/// States a dependency that one member has on another. -/// -/// -/// This can be used to inform tooling of a dependency that is otherwise not evident purely from -/// metadata and IL, for example a member relied on via reflection. -/// -[AttributeUsage( - AttributeTargets.Constructor | AttributeTargets.Field | AttributeTargets.Method, - AllowMultiple = true, Inherited = false)] -internal sealed class DynamicDependencyAttribute : Attribute -{ - /// - /// Initializes a new instance of the class - /// with the specified signature of a member on the same type as the consumer. - /// - /// The signature of the member depended on. - public DynamicDependencyAttribute(string memberSignature) - { - MemberSignature = memberSignature; - } - - /// - /// Initializes a new instance of the class - /// with the specified signature of a member on a . - /// - /// The signature of the member depended on. - /// The containing . - public DynamicDependencyAttribute(string memberSignature, Type type) - { - MemberSignature = memberSignature; - Type = type; - } - - /// - /// Initializes a new instance of the class - /// with the specified signature of a member on a type in an assembly. - /// - /// The signature of the member depended on. - /// The full name of the type containing the specified member. - /// The assembly name of the type containing the specified member. - public DynamicDependencyAttribute(string memberSignature, string typeName, string assemblyName) - { - MemberSignature = memberSignature; - TypeName = typeName; - AssemblyName = assemblyName; - } - - /// - /// Initializes a new instance of the class - /// with the specified types of members on a . - /// - /// The types of members depended on. - /// The containing the specified members. - public DynamicDependencyAttribute(DynamicallyAccessedMemberTypes memberTypes, Type type) - { - MemberTypes = memberTypes; - Type = type; - } - - /// - /// Initializes a new instance of the class - /// with the specified types of members on a type in an assembly. - /// - /// The types of members depended on. - /// The full name of the type containing the specified members. - /// The assembly name of the type containing the specified members. - public DynamicDependencyAttribute(DynamicallyAccessedMemberTypes memberTypes, string typeName, string assemblyName) - { - MemberTypes = memberTypes; - TypeName = typeName; - AssemblyName = assemblyName; - } - - /// - /// Gets the signature of the member depended on. - /// - /// - /// Either must be a valid string or - /// must not equal , but not both. - /// - public string? MemberSignature { get; } - - /// - /// Gets the which specifies the type - /// of members depended on. - /// - /// - /// Either must be a valid string or - /// must not equal , but not both. - /// - public DynamicallyAccessedMemberTypes MemberTypes { get; } - - /// - /// Gets the containing the specified member. - /// - /// - /// If neither nor are specified, - /// the type of the consumer is assumed. - /// - public Type? Type { get; } - - /// - /// Gets the full name of the type containing the specified member. - /// - /// - /// If neither nor are specified, - /// the type of the consumer is assumed. - /// - public string? TypeName { get; } - - /// - /// Gets the assembly name of the specified type. - /// - /// - /// is only valid when is specified. - /// - public string? AssemblyName { get; } - - /// - /// Gets or sets the condition in which the dependency is applicable, e.g. "DEBUG". - /// - public string? Condition { get; set; } -} - -/// -/// Indicates that certain members on a specified are accessed dynamically, -/// for example through . -/// -/// -/// This allows tools to understand which members are being accessed during the execution -/// of a program. -/// -/// This attribute is valid on members whose type is or . -/// -/// When this attribute is applied to a location of type , the assumption is -/// that the string represents a fully qualified type name. -/// -/// When this attribute is applied to a class, interface, or struct, the members specified -/// can be accessed dynamically on instances returned from calling -/// on instances of that class, interface, or struct. -/// -/// If the attribute is applied to a method it's treated as a special case and it implies -/// the attribute should be applied to the "this" parameter of the method. As such the attribute -/// should only be used on instance methods of types assignable to System.Type (or string, but no methods -/// will use it there). -/// -[AttributeUsage( - AttributeTargets.Field | AttributeTargets.ReturnValue | AttributeTargets.GenericParameter | - AttributeTargets.Parameter | AttributeTargets.Property | AttributeTargets.Method | - AttributeTargets.Class | AttributeTargets.Interface | AttributeTargets.Struct, - Inherited = false)] -internal sealed class DynamicallyAccessedMembersAttribute : Attribute -{ - /// - /// Initializes a new instance of the class - /// with the specified member types. - /// - /// The types of members dynamically accessed. - public DynamicallyAccessedMembersAttribute(DynamicallyAccessedMemberTypes memberTypes) - { - MemberTypes = memberTypes; - } - - /// - /// Gets the which specifies the type - /// of members dynamically accessed. - /// - public DynamicallyAccessedMemberTypes MemberTypes { get; } -} - -/// -/// Specifies the types of members that are dynamically accessed. -/// -/// This enumeration has a attribute that allows a -/// bitwise combination of its member values. -/// -[Flags] -internal enum DynamicallyAccessedMemberTypes -{ - /// - /// Specifies no members. - /// - None = 0, - - /// - /// Specifies the default, parameterless public constructor. - /// - PublicParameterlessConstructor = 0x0001, - - /// - /// Specifies all public constructors. - /// - PublicConstructors = 0x0002 | PublicParameterlessConstructor, - - /// - /// Specifies all non-public constructors. - /// - NonPublicConstructors = 0x0004, - - /// - /// Specifies all public methods. - /// - PublicMethods = 0x0008, - - /// - /// Specifies all non-public methods. - /// - NonPublicMethods = 0x0010, - - /// - /// Specifies all public fields. - /// - PublicFields = 0x0020, - - /// - /// Specifies all non-public fields. - /// - NonPublicFields = 0x0040, - - /// - /// Specifies all public nested types. - /// - PublicNestedTypes = 0x0080, - - /// - /// Specifies all non-public nested types. - /// - NonPublicNestedTypes = 0x0100, - - /// - /// Specifies all public properties. - /// - PublicProperties = 0x0200, - - /// - /// Specifies all non-public properties. - /// - NonPublicProperties = 0x0400, - - /// - /// Specifies all public events. - /// - PublicEvents = 0x0800, - - /// - /// Specifies all non-public events. - /// - NonPublicEvents = 0x1000, - - /// - /// Specifies all interfaces implemented by the type. - /// - Interfaces = 0x2000, - - /// - /// Specifies all members. - /// - All = ~None -} -#endif From 8c424cf14e315dc8ce86da2fd2b9c35789144923 Mon Sep 17 00:00:00 2001 From: HavenDV Date: Wed, 13 Nov 2024 12:17:46 +0400 Subject: [PATCH 8/9] feat: Added Trimmable property group. --- src/OpenAI.csproj | 8 ++++++++ 1 file changed, 8 insertions(+) diff --git a/src/OpenAI.csproj b/src/OpenAI.csproj index 4fa5cf944..a5f332b2c 100644 --- a/src/OpenAI.csproj +++ b/src/OpenAI.csproj @@ -80,4 +80,12 @@ + + + true + true + true + false + false + From e869710ca33f5183c8deffdd7a47d94b6e48206f Mon Sep 17 00:00:00 2001 From: HavenDV Date: Thu, 14 Nov 2024 09:40:52 +0400 Subject: [PATCH 9/9] fix: Fixed possible warning for IsAotCompatible. --- src/OpenAI.csproj | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/src/OpenAI.csproj b/src/OpenAI.csproj index a5f332b2c..a09b86397 100644 --- a/src/OpenAI.csproj +++ b/src/OpenAI.csproj @@ -82,7 +82,7 @@ - true + true true true false