mirror of
https://github.com/microsoft/agent-framework.git
synced 2026-06-16 21:04:09 +08:00
* Use actual message role when creating ChatMessage Replace hard-coded ChatRole.User with a ChatRole constructed from the message's Role. The change ensures ToChatMessage and FunctionMessage use the original role (new ChatRole(this.Role)) for both text and contents branches, fixing incorrect role assignment when constructing ChatMessage instances. * Update changes * Fix formatting in ToChatMessage tests --------- Co-authored-by: Roger Barreto <19890735+rogerbarreto@users.noreply.github.com>
180 lines
5.7 KiB
C#
180 lines
5.7 KiB
C#
// Copyright (c) Microsoft. All rights reserved.
|
|
|
|
using System;
|
|
using System.Linq;
|
|
using System.Text.Json.Serialization;
|
|
using Microsoft.Agents.AI.Hosting.OpenAI.ChatCompletions.Converters;
|
|
using Microsoft.Extensions.AI;
|
|
|
|
namespace Microsoft.Agents.AI.Hosting.OpenAI.ChatCompletions.Models;
|
|
|
|
/// <summary>
|
|
/// Represents a message in a chat completion request.
|
|
/// </summary>
|
|
[JsonPolymorphic(TypeDiscriminatorPropertyName = "role", UnknownDerivedTypeHandling = JsonUnknownDerivedTypeHandling.FailSerialization)]
|
|
[JsonDerivedType(typeof(DeveloperMessage), "developer")]
|
|
[JsonDerivedType(typeof(SystemMessage), "system")]
|
|
[JsonDerivedType(typeof(UserMessage), "user")]
|
|
[JsonDerivedType(typeof(AssistantMessage), "assistant")]
|
|
[JsonDerivedType(typeof(ToolMessage), "tool")]
|
|
[JsonDerivedType(typeof(FunctionMessage), "function")]
|
|
internal abstract record ChatCompletionRequestMessage
|
|
{
|
|
/// <summary>
|
|
/// The role of the content.
|
|
/// </summary>
|
|
[JsonIgnore]
|
|
public abstract string Role { get; }
|
|
|
|
/// <summary>
|
|
/// The contents of the message.
|
|
/// </summary>
|
|
[JsonPropertyName("content")]
|
|
public required MessageContent Content { get; init; }
|
|
|
|
/// <summary>
|
|
/// Converts to a <see cref="ChatMessage"/>.
|
|
/// </summary>
|
|
/// <returns>A <see cref="ChatMessage"/> representing the message.</returns>
|
|
/// <exception cref="InvalidOperationException">Thrown when the content is neither text nor AI contents.</exception>
|
|
public virtual ChatMessage ToChatMessage()
|
|
{
|
|
var role = new ChatRole(this.Role);
|
|
|
|
if (this.Content.IsText)
|
|
{
|
|
return new(role, this.Content.Text);
|
|
}
|
|
else if (this.Content.IsContents)
|
|
{
|
|
var aiContents = this.Content.Contents.Select(MessageContentPartConverter.ToAIContent).Where(c => c is not null).ToList();
|
|
return new ChatMessage(role, aiContents!);
|
|
}
|
|
|
|
throw new InvalidOperationException("MessageContent has no value");
|
|
}
|
|
}
|
|
|
|
/// <summary>
|
|
/// A developer message in a chat completion request.
|
|
/// Developer messages are used to provide instructions to the model at the system level.
|
|
/// </summary>
|
|
internal sealed record DeveloperMessage : ChatCompletionRequestMessage
|
|
{
|
|
/// <inheritdoc/>
|
|
[JsonIgnore]
|
|
public override string Role => "developer";
|
|
|
|
/// <summary>
|
|
/// An optional name for the participant.
|
|
/// Provides the model information to differentiate between participants of the same role.
|
|
/// </summary>
|
|
[JsonPropertyName("name")]
|
|
public string? Name { get; init; }
|
|
}
|
|
|
|
/// <summary>
|
|
/// A system message in a chat completion request.
|
|
/// System messages provide high-level instructions for the conversation.
|
|
/// </summary>
|
|
internal sealed record SystemMessage : ChatCompletionRequestMessage
|
|
{
|
|
/// <inheritdoc/>
|
|
[JsonIgnore]
|
|
public override string Role => "system";
|
|
|
|
/// <summary>
|
|
/// An optional name for the participant.
|
|
/// Provides the model information to differentiate between participants of the same role.
|
|
/// </summary>
|
|
[JsonPropertyName("name")]
|
|
public string? Name { get; init; }
|
|
}
|
|
|
|
/// <summary>
|
|
/// A user message in a chat completion request.
|
|
/// User messages represent input from the end user.
|
|
/// </summary>
|
|
internal sealed record UserMessage : ChatCompletionRequestMessage
|
|
{
|
|
/// <inheritdoc/>
|
|
[JsonIgnore]
|
|
public override string Role => "user";
|
|
|
|
/// <summary>
|
|
/// An optional name for the participant.
|
|
/// Provides the model information to differentiate between participants of the same role.
|
|
/// </summary>
|
|
[JsonPropertyName("name")]
|
|
public string? Name { get; init; }
|
|
}
|
|
|
|
/// <summary>
|
|
/// An assistant message in a chat completion request.
|
|
/// Assistant messages represent previous responses from the model, used in multi-turn conversations.
|
|
/// </summary>
|
|
internal sealed record AssistantMessage : ChatCompletionRequestMessage
|
|
{
|
|
/// <inheritdoc/>
|
|
[JsonIgnore]
|
|
public override string Role => "assistant";
|
|
|
|
/// <summary>
|
|
/// An optional name for the participant.
|
|
/// Provides the model information to differentiate between participants of the same role.
|
|
/// </summary>
|
|
[JsonPropertyName("name")]
|
|
public string? Name { get; init; }
|
|
}
|
|
|
|
/// <summary>
|
|
/// A tool message in a chat completion request.
|
|
/// Tool messages contain the result of a tool call made by the assistant.
|
|
/// </summary>
|
|
internal sealed record ToolMessage : ChatCompletionRequestMessage
|
|
{
|
|
/// <inheritdoc/>
|
|
[JsonIgnore]
|
|
public override string Role => "tool";
|
|
|
|
/// <summary>
|
|
/// Tool call that this message is responding to.
|
|
/// </summary>
|
|
[JsonPropertyName("tool_call_id")]
|
|
public required string ToolCallId { get; set; }
|
|
}
|
|
|
|
/// <summary>
|
|
/// Deprecated. A function message in a chat completion request.
|
|
/// Function messages have been replaced by tool messages.
|
|
/// </summary>
|
|
internal sealed record FunctionMessage : ChatCompletionRequestMessage
|
|
{
|
|
/// <inheritdoc/>
|
|
[JsonIgnore]
|
|
public override string Role => "function";
|
|
|
|
/// <summary>
|
|
/// The name of the function to call.
|
|
/// </summary>
|
|
[JsonPropertyName("name")]
|
|
public required string Name { get; init; }
|
|
|
|
/// <summary>
|
|
/// Converts to a <see cref="ChatMessage"/>.
|
|
/// </summary>
|
|
/// <returns>A <see cref="ChatMessage"/> representing the message.</returns>
|
|
/// <exception cref="InvalidOperationException">Thrown when the content is not text.</exception>
|
|
public override ChatMessage ToChatMessage()
|
|
{
|
|
var role = new ChatRole(this.Role);
|
|
|
|
if (this.Content.IsText)
|
|
{
|
|
return new(role, this.Content.Text);
|
|
}
|
|
|
|
throw new InvalidOperationException("FunctionMessage Content must be text");
|
|
}
|
|
}
|