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

Skip to content
Merged
Show file tree
Hide file tree
Changes from 1 commit
Commits
Show all changes
31 commits
Select commit Hold shift + click to select a range
3ac172a
Merged PR 49897: Changes in preparation of 9.5 stable release
joperezr May 9, 2025
535c58c
Translate OpenAI refusals to ErrorContent (#6393)
stephentoub May 8, 2025
bab3b06
Rename useJsonSchema parameter (#6394)
stephentoub May 8, 2025
4ccd5dc
Add JSON schema transformation functionality to `AIJsonUtilities` (#6…
eiriktsarpalis May 8, 2025
f31b5f0
Remove CacheOptions from DiskBasedResponseCache (#6395)
shyamnamboodiripad May 8, 2025
c30c042
Add ChatOptions.RawRepresentationFactory (#6319)
jozkee May 8, 2025
b95b26d
Avoid caching in CachingChatClient when ConversationId is set (#6400)
stephentoub May 9, 2025
fbf6b45
Add comment LoggingChatClient et al trace-level logging (#6391)
stephentoub May 9, 2025
2e71b1e
Fix test validation of aggregate usage counts (#6401)
stephentoub May 9, 2025
90c4fa9
Add back net9.0 version of the aieval dotnet tool (#6396)
shyamnamboodiripad May 8, 2025
49bb2c5
Add BinaryEmbedding (#6398)
stephentoub May 9, 2025
6828de6
Add some additional documentation around usage of cache, and CSP prop…
peterwald May 8, 2025
118d4e6
Bump vite from 6.2.6 to 6.3.4 in /src/Libraries/Microsoft.Extensions.…
dependabot[bot] May 9, 2025
6753e51
Some API related fixes for the evaluation libraries (#6402)
shyamnamboodiripad May 9, 2025
2d442e1
Allow image rendering in evaluation report (#6407)
shyamnamboodiripad May 9, 2025
a3d136b
Merged PR 49950: Update Microsoft.Extensions.AI and Microsoft.Extensi…
jeffhandley May 9, 2025
f6bd93c
Merged PR 49951: [AI Evaluation] Cherry pick commits for 9.5 preview …
May 9, 2025
7a1b919
Merge from release/9.4 into main, updating
jeffhandley May 1, 2025
4ec4f85
Move AIFunctionFactory down to M.E.AI.Abstractions (#6412)
stephentoub May 10, 2025
1ba107a
Fix handling of tool calls with some OpenAI endpoints (#6405)
stephentoub May 10, 2025
aa6ca66
Merged PR 49960: Merge MEAI updates from main into 9.5.0 release
jeffhandley May 10, 2025
0fe91fa
Add missing [DebuggerDisplay] on AIFunctionArguments (#6422)
stephentoub May 12, 2025
43adf49
Add WriteAsync overrides to stream helper in AIFunctionFactory (#6419)
stephentoub May 12, 2025
3e6df02
Update CHANGELOGs for M.E.AI (#6416)
stephentoub May 12, 2025
f49a64a
Replace Type targetType AIFunctionFactory.Create parameter with a fun…
stephentoub May 12, 2025
57d0da3
Remove debug-level logging of updates in LoggingChatClient (#6425)
stephentoub May 12, 2025
70a88cc
Add an AIJsonSchemaTransformOptions property inside AIJsonSchemaCreat…
eiriktsarpalis May 12, 2025
5575f4b
Merged PR 49993: Merge MEAI updates from main
jeffhandley May 12, 2025
ca17a41
Merge internal changes
joperezr May 13, 2025
c2f7b38
Update MEAI Template test snapshots
jeffhandley May 14, 2025
5aab00e
Pin the non-AI package versions for the MEAI Templates
jeffhandley May 14, 2025
File filter

Filter by extension

Filter by extension


Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
Prev Previous commit
Next Next commit
Add ChatOptions.RawRepresentationFactory (#6319)
* Look for OpenAI.ChatCompletionOptions in top-level additional properties and stop looking for individually specific additional properties

* Add RawRepresentation to ChatOptions and use it in OpenAI and AzureAIInference

* Remove now unused locals

* Add [JsonIgnore] and update roundtrip tests

* Overwirte properties only if the underlying model don't specify it already

* Clone RawRepresentation

* Reflection workaround for ToolChoice not being cloned

* Style changes

* AI.Inference: Bring back propagation of additional properties

* Don't use 0.1f, it doesn't roundtrip properly in .NET Framework

* Add RawRepresentationFactory instead of object? property

* Augment remarks to discourage returning shared instances

* Documentation feedback

* AI.Inference: keep passing TopK as AdditionalProperty if not already there
  • Loading branch information
jozkee authored and jeffhandley committed May 9, 2025
commit c30c042bd2d743db04c23e664104aa13e7dee656
Original file line number Diff line number Diff line change
@@ -1,6 +1,7 @@
// 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.Text.Json.Serialization;

Expand Down Expand Up @@ -121,6 +122,26 @@ public string? ChatThreadId
[JsonIgnore]
public IList<AITool>? Tools { get; set; }

/// <summary>
/// Gets or sets a callback responsible of creating the raw representation of the chat options from an underlying implementation.
/// </summary>
/// <remarks>
/// The underlying <see cref="IChatClient" /> implementation may have its own representation of options.
/// When <see cref="IChatClient.GetResponseAsync" /> or <see cref="IChatClient.GetStreamingResponseAsync" />
/// is invoked with a <see cref="ChatOptions" />, that implementation may convert the provided options into
/// its own representation in order to use it while performing the operation. For situations where a consumer knows
/// which concrete <see cref="IChatClient" /> is being used and how it represents options, a new instance of that
/// implementation-specific options type may be returned by this callback, for the <see cref="IChatClient" />
/// implementation to use instead of creating a new instance. Such implementations may mutate the supplied options
/// instance further based on other settings supplied on this <see cref="ChatOptions" /> instance or from other inputs,
/// like the enumerable of <see cref="ChatMessage"/>s, therefore, its **strongly recommended** to not return shared instances
/// and instead make the callback return a new instance per each call.
/// This is typically used to set an implementation-specific setting that isn't otherwise exposed from the strongly-typed
/// properties on <see cref="ChatOptions" />.
/// </remarks>
[JsonIgnore]
public Func<IChatClient, object?>? RawRepresentationFactory { get; set; }

/// <summary>Gets or sets any additional properties associated with the options.</summary>
public AdditionalPropertiesDictionary? AdditionalProperties { get; set; }

Expand All @@ -147,6 +168,7 @@ public virtual ChatOptions Clone()
ModelId = ModelId,
AllowMultipleToolCalls = AllowMultipleToolCalls,
ToolMode = ToolMode,
RawRepresentationFactory = RawRepresentationFactory,
AdditionalProperties = AdditionalProperties?.Clone(),
};

Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -281,66 +281,74 @@ private static ChatRole ToChatRole(global::Azure.AI.Inference.ChatRole role) =>
finishReason == CompletionsFinishReason.ToolCalls ? ChatFinishReason.ToolCalls :
new(s);

private ChatCompletionsOptions CreateAzureAIOptions(IEnumerable<ChatMessage> chatContents, ChatOptions? options) =>
new(ToAzureAIInferenceChatMessages(chatContents))
{
Model = options?.ModelId ?? _metadata.DefaultModelId ??
throw new InvalidOperationException("No model id was provided when either constructing the client or in the chat options.")
};

/// <summary>Converts an extensions options instance to an AzureAI options instance.</summary>
private ChatCompletionsOptions ToAzureAIOptions(IEnumerable<ChatMessage> chatContents, ChatOptions? options)
{
ChatCompletionsOptions result = new(ToAzureAIInferenceChatMessages(chatContents))
if (options is null)
{
Model = options?.ModelId ?? _metadata.DefaultModelId ?? throw new InvalidOperationException("No model id was provided when either constructing the client or in the chat options.")
};
return CreateAzureAIOptions(chatContents, options);
}

if (options.RawRepresentationFactory?.Invoke(this) is ChatCompletionsOptions result)
{
result.Messages = ToAzureAIInferenceChatMessages(chatContents).ToList();
result.Model ??= options.ModelId ?? _metadata.DefaultModelId ??
throw new InvalidOperationException("No model id was provided when either constructing the client or in the chat options.");
}
else
{
result = CreateAzureAIOptions(chatContents, options);
}

if (options is not null)
result.FrequencyPenalty ??= options.FrequencyPenalty;
result.MaxTokens ??= options.MaxOutputTokens;
result.NucleusSamplingFactor ??= options.TopP;
result.PresencePenalty ??= options.PresencePenalty;
result.Temperature ??= options.Temperature;
result.Seed ??= options.Seed;

if (options.StopSequences is { Count: > 0 } stopSequences)
{
result.FrequencyPenalty = options.FrequencyPenalty;
result.MaxTokens = options.MaxOutputTokens;
result.NucleusSamplingFactor = options.TopP;
result.PresencePenalty = options.PresencePenalty;
result.Temperature = options.Temperature;
result.Seed = options.Seed;

if (options.StopSequences is { Count: > 0 } stopSequences)
foreach (string stopSequence in stopSequences)
{
foreach (string stopSequence in stopSequences)
{
result.StopSequences.Add(stopSequence);
}
result.StopSequences.Add(stopSequence);
}
}

// This property is strongly typed on ChatOptions but not on ChatCompletionsOptions.
if (options.TopK is int topK && !result.AdditionalProperties.ContainsKey("top_k"))
{
result.AdditionalProperties["top_k"] = new BinaryData(JsonSerializer.SerializeToUtf8Bytes(topK, AIJsonUtilities.DefaultOptions.GetTypeInfo(typeof(int))));
}

// These properties are strongly typed on ChatOptions but not on ChatCompletionsOptions.
if (options.TopK is int topK)
if (options.AdditionalProperties is { } props)
{
foreach (var prop in props)
{
result.AdditionalProperties["top_k"] = new BinaryData(JsonSerializer.SerializeToUtf8Bytes(topK, AIJsonUtilities.DefaultOptions.GetTypeInfo(typeof(int))));
byte[] data = JsonSerializer.SerializeToUtf8Bytes(prop.Value, AIJsonUtilities.DefaultOptions.GetTypeInfo(typeof(object)));
result.AdditionalProperties[prop.Key] = new BinaryData(data);
}
}

if (options.AdditionalProperties is { } props)
if (options.Tools is { Count: > 0 } tools)
{
foreach (AITool tool in tools)
{
foreach (var prop in props)
if (tool is AIFunction af)
{
switch (prop.Key)
{
// Propagate everything else to the ChatCompletionsOptions' AdditionalProperties.
default:
if (prop.Value is not null)
{
byte[] data = JsonSerializer.SerializeToUtf8Bytes(prop.Value, AIJsonUtilities.DefaultOptions.GetTypeInfo(typeof(object)));
result.AdditionalProperties[prop.Key] = new BinaryData(data);
}

break;
}
result.Tools.Add(ToAzureAIChatTool(af));
}
}

if (options.Tools is { Count: > 0 } tools)
if (result.ToolChoice is null && result.Tools.Count > 0)
{
foreach (AITool tool in tools)
{
if (tool is AIFunction af)
{
result.Tools.Add(ToAzureAIChatTool(af));
}
}

switch (options.ToolMode)
{
case NoneChatToolMode:
Expand All @@ -359,7 +367,10 @@ private ChatCompletionsOptions ToAzureAIOptions(IEnumerable<ChatMessage> chatCon
break;
}
}
}

if (result.ResponseFormat is null)
{
if (options.ResponseFormat is ChatResponseFormatText)
{
result.ResponseFormat = ChatCompletionsResponseFormat.CreateTextFormat();
Expand Down
Loading