using System.Text.Json.Serialization;
using AnthropicClient.Utils;
namespace AnthropicClient.Models;
///
/// Represents a message request.
///
public abstract class BaseMessageRequest
{
///
/// Gets the model ID to use for the request.
///
public string Model { get; init; } = string.Empty;
// TODO: I do not like this. I would prefer to have a single property that is a list of TextContent objects.
// This approach was taken to maintain compatibility with the API. As someone could be using the System property
// and changing it to a list of TextContent objects would break their code.
// However if an opportunity arises for a breaking change release, this should be changed.
///
/// Gets the system message that will be used as the system prompt if no system messages are provided.
///
[JsonIgnore]
public string? System { get; init; } = null;
///
/// Gets the system messages to send to the model to be used as the system prompt.
///
[JsonIgnore]
public List? SystemMessages { get; init; } = null;
///
/// Gets the system prompt that will be used for the request.
/// If will return the system messages if they are provided, otherwise it will return the system message.
/// If neither are provided, it will return null.
///
[JsonPropertyName("system")]
public List? SystemPrompt => GetSystemPrompt();
private List? GetSystemPrompt()
{
if (SystemMessages is not null)
{
return SystemMessages;
}
if (System is not null)
{
return [new TextContent(System)];
}
return null;
}
///
/// Gets the messages to send to the model.
///
public List Messages { get; init; } = [];
///
/// Gets the maximum number of tokens to generate.
///
[JsonPropertyName("max_tokens")]
public int MaxTokens { get; init; } = 1024;
///
/// Gets the metadata to include with the request.
///
public Dictionary? Metadata { get; init; } = null;
///
/// Gets the prompt stop sequences.
///
[JsonPropertyName("stop_sequences")]
public List StopSequences { get; init; } = [];
///
/// Gets the temperature to use for the request.
///
public decimal Temperature { get; init; } = 0.0m;
///
/// Gets the top-K value to use for the request.
///
public int? TopK { get; init; } = null;
///
/// Gets the top-P value to use for the request.
///
public decimal? TopP { get; init; } = null;
///
/// Gets the tool choice mode to use for the request.
///
[JsonPropertyName("tool_choice")]
public ToolChoice? ToolChoice { get; init; } = null;
///
/// Gets the tools to use for the request.
///
public List? Tools { get; init; } = null;
///
/// Gets a value indicating whether the message should be streamed.
///
public bool Stream { get; init; }
[JsonConstructor]
internal BaseMessageRequest() { }
///
/// Initializes a new instance of the class.
///
/// The model ID to use for the request.
/// The messages to send to the model.
/// The maximum number of tokens to generate.
/// The system prompt to use for the request.
/// The metadata to include with the request.
/// The temperature to use for the request.
/// The top-K value to use for the request.
/// The top-P value to use for the request.
/// The tool choice mode to use for the request.
/// The tools to use for the request.
/// A value indicating whether the message should be streamed.
/// The prompt stop sequences.
/// The system messages to use for the request.
/// Thrown when the model or messages is null.
/// Thrown when the messages contain no messages.
/// Thrown when the max tokens is less than one.
/// Thrown when the temperature is less than zero or greater than one.
/// A new instance of the class.
protected BaseMessageRequest(
string model,
List messages,
int maxTokens,
string? system,
Dictionary? metadata,
decimal temperature,
int? topK,
decimal? topP,
ToolChoice? toolChoice,
List? tools,
bool stream,
List? stopSequences,
List? systemMessages
)
{
ArgumentValidator.ThrowIfNull(model, nameof(model));
ArgumentValidator.ThrowIfNull(messages, nameof(messages));
if (messages.Count < 1)
{
throw new ArgumentException("Messages must contain at least one message");
}
if (maxTokens < 1)
{
throw new ArgumentException($"Invalid max tokens: {maxTokens}");
}
if (temperature < 0.0m || temperature > 1.0m)
{
throw new ArgumentException($"Invalid temperature: {temperature}");
}
Model = model;
Messages = messages;
MaxTokens = maxTokens;
System = system;
SystemMessages = systemMessages;
Metadata = metadata;
Temperature = temperature;
TopK = topK;
TopP = topP;
ToolChoice = toolChoice;
Tools = tools;
Stream = stream;
StopSequences = stopSequences ?? [];
}
}