mirror of
https://github.com/microsoft/agent-framework.git
synced 2026-06-16 21:04:09 +08:00
* .NET: Delete AgentResponse.{Try}Deserialize<T> methods (#3518)
* delete deserialize method of agent response
* order usings
* Update dotnet/samples/GettingStarted/FoundryAgents/FoundryAgents_Step05_StructuredOutput/Program.cs
Co-authored-by: Copilot <175728472+Copilot@users.noreply.github.com>
* Update dotnet/samples/GettingStarted/Workflows/_Foundational/08_WriterCriticWorkflow/Program.cs
Co-authored-by: Copilot <175728472+Copilot@users.noreply.github.com>
* Update dotnet/samples/GettingStarted/AGUI/Step05_StateManagement/Server/SharedStateAgent.cs
Co-authored-by: Copilot <175728472+Copilot@users.noreply.github.com>
* Update dotnet/samples/AGUIClientServer/AGUIDojoServer/SharedState/SharedStateAgent.cs
Co-authored-by: Copilot <175728472+Copilot@users.noreply.github.com>
* Update dotnet/samples/M365Agent/Agents/WeatherForecastAgent.cs
Co-authored-by: Copilot <175728472+Copilot@users.noreply.github.com>
---------
Co-authored-by: Copilot <175728472+Copilot@users.noreply.github.com>
* .NET:[Breaking] Add support for structured output (#3658)
* add support for so
* restore lost xml comment part
* fix using ordering
* Update dotnet/src/Microsoft.Agents.AI.Abstractions/AIAgentStructuredOutput.cs
Co-authored-by: Copilot <175728472+Copilot@users.noreply.github.com>
* Update dotnet/src/Microsoft.Agents.AI.Abstractions/AIAgentStructuredOutput.cs
Co-authored-by: Copilot <175728472+Copilot@users.noreply.github.com>
* Update dotnet/tests/Microsoft.Agents.AI.UnitTests/ChatClient/ChatClientAgent_SO_WithFormatResponseTests.cs
Co-authored-by: Copilot <175728472+Copilot@users.noreply.github.com>
* addressw pr review comments
* address pr review feedback
* address pr review comments
* fix compilation issues after the latest merge with main
* remove unnecessry options
* remove RunAsync<object> methods
* address code review feedback
* address pr review feedback
* make copy constructor protected
* address pr review feedback
---------
Co-authored-by: Copilot <175728472+Copilot@users.noreply.github.com>
* .NET: Add decorator for structured output support (#3694)
* add decorator that adds structured output support to agents that don't natively support it.
* Update dotnet/src/Microsoft.Agents.AI/StructuredOutput/StructuredOutputAgentResponse.cs
Co-authored-by: westey <164392973+westey-m@users.noreply.github.com>
* Update dotnet/samples/GettingStarted/Agents/Agent_Step05_StructuredOutput/Program.cs
Co-authored-by: westey <164392973+westey-m@users.noreply.github.com>
* address pr review feedback
---------
Co-authored-by: westey <164392973+westey-m@users.noreply.github.com>
* .NET: Support primitives and arrays for SO (#3696)
* wrap primitives and arrays
* fix file encoding
* address review comments
* add adr
* add missed change
* fix compilation issue
* address review comments
* rename adr file name
* reflect decision to have SO decorator as a reference implementation in samples
* .NET: Move SO agent to samples (#3820)
* move SO agent to samples
* change file encoding
* fix files encoding
* .NET: Preserve caller context (#3803)
* fix stuck orchestration
* add previously removed RunAsync<T> method to DurableAIAgent
* suppress IDE0005 warning
* update changelog and remove unused constructor of AgentResponse<T>
* updatge the changelog
* address PR review feedback
* .NET: Disable irrelevant integration test (#3913)
* disable irrelevant integration test
* Update dotnet/tests/AzureAI.IntegrationTests/AIProjectClientAgentStructuredOutputRunTests.cs
Co-authored-by: Copilot <175728472+Copilot@users.noreply.github.com>
---------
Co-authored-by: Copilot <175728472+Copilot@users.noreply.github.com>
* forgotten change
* address pr review feedback
* disable intermittently failing integration test.
---------
Co-authored-by: Copilot <175728472+Copilot@users.noreply.github.com>
Co-authored-by: westey <164392973+westey-m@users.noreply.github.com>
99 lines
3.6 KiB
C#
99 lines
3.6 KiB
C#
// Copyright (c) Microsoft. All rights reserved.
|
|
|
|
using System;
|
|
#if NET
|
|
using System.Buffers;
|
|
#endif
|
|
|
|
#if NET
|
|
using System.Text;
|
|
#endif
|
|
using System.Text.Json;
|
|
using System.Text.Json.Serialization;
|
|
using System.Text.Json.Serialization.Metadata;
|
|
using Microsoft.Shared.Diagnostics;
|
|
|
|
namespace Microsoft.Agents.AI;
|
|
|
|
/// <summary>
|
|
/// Represents the response of the specified type <typeparamref name="T"/> to an <see cref="AIAgent"/> run request.
|
|
/// </summary>
|
|
/// <typeparam name="T">The type of value expected from the agent.</typeparam>
|
|
public class AgentResponse<T> : AgentResponse
|
|
{
|
|
private readonly JsonSerializerOptions _serializerOptions;
|
|
|
|
/// <summary>
|
|
/// Initializes a new instance of the <see cref="AgentResponse{T}"/> class.
|
|
/// </summary>
|
|
/// <param name="response">The <see cref="AgentResponse"/> from which to populate this <see cref="AgentResponse{T}"/>.</param>
|
|
/// <param name="serializerOptions">The <see cref="JsonSerializerOptions"/> to use when deserializing the result.</param>
|
|
/// <exception cref="ArgumentNullException"><paramref name="serializerOptions"/> is <see langword="null"/>.</exception>
|
|
public AgentResponse(AgentResponse response, JsonSerializerOptions serializerOptions) : base(response)
|
|
{
|
|
_ = Throw.IfNull(serializerOptions);
|
|
|
|
this._serializerOptions = serializerOptions;
|
|
}
|
|
|
|
/// <summary>
|
|
/// Gets or sets a value indicating whether the JSON schema has an extra object wrapper.
|
|
/// </summary>
|
|
/// <remarks>
|
|
/// The wrapper is required for any non-JSON-object-typed values such as numbers, enum values, and arrays.
|
|
/// </remarks>
|
|
public bool IsWrappedInObject { get; init; }
|
|
|
|
/// <summary>
|
|
/// Gets the result value of the agent response as an instance of <typeparamref name="T"/>.
|
|
/// </summary>
|
|
[JsonIgnore]
|
|
public virtual T Result
|
|
{
|
|
get
|
|
{
|
|
var json = this.Text;
|
|
if (string.IsNullOrEmpty(json))
|
|
{
|
|
throw new InvalidOperationException("The response did not contain JSON to be deserialized.");
|
|
}
|
|
|
|
if (this.IsWrappedInObject)
|
|
{
|
|
json = StructuredOutputSchemaUtilities.UnwrapResponseData(json!);
|
|
}
|
|
|
|
T? deserialized = DeserializeFirstTopLevelObject(json!, (JsonTypeInfo<T>)this._serializerOptions.GetTypeInfo(typeof(T)));
|
|
if (deserialized is null)
|
|
{
|
|
throw new InvalidOperationException("The deserialized response is null.");
|
|
}
|
|
|
|
return deserialized;
|
|
}
|
|
}
|
|
|
|
private static T? DeserializeFirstTopLevelObject(string json, JsonTypeInfo<T> typeInfo)
|
|
{
|
|
#if NET
|
|
// We need to deserialize only the first top-level object as a workaround for a common LLM backend
|
|
// issue. GPT 3.5 Turbo commonly returns multiple top-level objects after doing a function call.
|
|
// See https://community.openai.com/t/2-json-objects-returned-when-using-function-calling-and-json-mode/574348
|
|
var utf8ByteLength = Encoding.UTF8.GetByteCount(json);
|
|
var buffer = ArrayPool<byte>.Shared.Rent(utf8ByteLength);
|
|
try
|
|
{
|
|
var utf8SpanLength = Encoding.UTF8.GetBytes(json, 0, json.Length, buffer, 0);
|
|
var reader = new Utf8JsonReader(new ReadOnlySpan<byte>(buffer, 0, utf8SpanLength), new() { AllowMultipleValues = true });
|
|
return JsonSerializer.Deserialize(ref reader, typeInfo);
|
|
}
|
|
finally
|
|
{
|
|
ArrayPool<byte>.Shared.Return(buffer);
|
|
}
|
|
#else
|
|
return JsonSerializer.Deserialize(json, typeInfo);
|
|
#endif
|
|
}
|
|
}
|