Files
replicate.maui/Replicate.Maui/IReplicateTransformer.cs
2025-12-10 21:59:12 -05:00

427 lines
16 KiB
C#

namespace MarketAlly.Replicate.Maui
{
/// <summary>
/// Type of transformation being performed.
/// </summary>
public enum TransformationType
{
Image,
Video
}
/// <summary>
/// Status of a prediction in the Replicate API.
/// </summary>
public enum PredictionStatus
{
/// <summary>
/// Prediction is starting up.
/// </summary>
Starting,
/// <summary>
/// Prediction is actively processing.
/// </summary>
Processing,
/// <summary>
/// Prediction completed successfully.
/// </summary>
Succeeded,
/// <summary>
/// Prediction failed with an error.
/// </summary>
Failed,
/// <summary>
/// Prediction was canceled by the user.
/// </summary>
Canceled,
/// <summary>
/// Unknown or unrecognized status.
/// </summary>
Unknown
}
/// <summary>
/// Helper extensions for PredictionStatus.
/// </summary>
public static class PredictionStatusExtensions
{
/// <summary>
/// Convert a status string from the API to a PredictionStatus enum.
/// </summary>
public static PredictionStatus ToPredictionStatus(this string? status)
{
return status?.ToLowerInvariant() switch
{
"starting" => PredictionStatus.Starting,
"processing" => PredictionStatus.Processing,
"succeeded" => PredictionStatus.Succeeded,
"failed" => PredictionStatus.Failed,
"canceled" => PredictionStatus.Canceled,
_ => PredictionStatus.Unknown
};
}
/// <summary>
/// Convert a PredictionStatus enum to the API string value.
/// </summary>
public static string ToApiString(this PredictionStatus status)
{
return status switch
{
PredictionStatus.Starting => "starting",
PredictionStatus.Processing => "processing",
PredictionStatus.Succeeded => "succeeded",
PredictionStatus.Failed => "failed",
PredictionStatus.Canceled => "canceled",
_ => "unknown"
};
}
/// <summary>
/// Whether this status represents a completed prediction (succeeded, failed, or canceled).
/// </summary>
public static bool IsCompleted(this PredictionStatus status)
{
return status is PredictionStatus.Succeeded or PredictionStatus.Failed or PredictionStatus.Canceled;
}
/// <summary>
/// Whether this status represents a pending prediction (starting or processing).
/// </summary>
public static bool IsPending(this PredictionStatus status)
{
return status is PredictionStatus.Starting or PredictionStatus.Processing;
}
}
/// <summary>
/// Event args for when a prediction is created (before polling starts).
/// </summary>
public class PredictionCreatedEventArgs : EventArgs
{
/// <summary>
/// The initial prediction result with ID and starting status.
/// </summary>
public PredictionResult Prediction { get; }
public PredictionCreatedEventArgs(PredictionResult prediction)
{
Prediction = prediction;
}
}
/// <summary>
/// Interface for Replicate API image and video transformations.
/// </summary>
public interface IReplicateTransformer
{
/// <summary>
/// Raised when a prediction is created (before polling starts).
/// Use this to track predictions immediately when they're submitted.
/// </summary>
event EventHandler<PredictionCreatedEventArgs>? PredictionCreated;
/// <summary>
/// Transform an image to anime style using raw bytes.
/// </summary>
/// <param name="imageBytes">The image bytes to transform.</param>
/// <param name="customPrompt">Optional custom prompt override.</param>
/// <param name="options">Optional prediction options (webhook, sync mode, etc.).</param>
/// <param name="cancellationToken">Cancellation token.</param>
/// <returns>Prediction result with output URL and metadata.</returns>
Task<PredictionResult> TransformToAnimeAsync(
byte[] imageBytes,
string? customPrompt = null,
PredictionOptions? options = null,
CancellationToken cancellationToken = default);
/// <summary>
/// Transform an image to anime style using base64 encoded string.
/// </summary>
/// <param name="base64Image">Base64 encoded image (with or without data URI prefix).</param>
/// <param name="customPrompt">Optional custom prompt override.</param>
/// <param name="options">Optional prediction options (webhook, sync mode, etc.).</param>
/// <param name="cancellationToken">Cancellation token.</param>
/// <returns>Prediction result with output URL and metadata.</returns>
Task<PredictionResult> TransformToAnimeFromBase64Async(
string base64Image,
string? customPrompt = null,
PredictionOptions? options = null,
CancellationToken cancellationToken = default);
/// <summary>
/// Transform an image to anime style from a URL.
/// </summary>
/// <param name="imageUrl">URL of the image to transform.</param>
/// <param name="customPrompt">Optional custom prompt override.</param>
/// <param name="options">Optional prediction options (webhook, sync mode, etc.).</param>
/// <param name="cancellationToken">Cancellation token.</param>
/// <returns>Prediction result with output URL and metadata.</returns>
Task<PredictionResult> TransformToAnimeFromUrlAsync(
string imageUrl,
string? customPrompt = null,
PredictionOptions? options = null,
CancellationToken cancellationToken = default);
/// <summary>
/// Generate a video from an image using raw bytes.
/// </summary>
/// <param name="imageBytes">The image bytes to animate.</param>
/// <param name="customPrompt">Optional custom prompt override.</param>
/// <param name="options">Optional prediction options (webhook, sync mode, etc.).</param>
/// <param name="cancellationToken">Cancellation token.</param>
/// <returns>Prediction result with output URL and metadata.</returns>
Task<PredictionResult> TransformToVideoAsync(
byte[] imageBytes,
string? customPrompt = null,
PredictionOptions? options = null,
CancellationToken cancellationToken = default);
/// <summary>
/// Generate a video from a base64 encoded image.
/// </summary>
/// <param name="base64Image">Base64 encoded image (with or without data URI prefix).</param>
/// <param name="customPrompt">Optional custom prompt override.</param>
/// <param name="options">Optional prediction options (webhook, sync mode, etc.).</param>
/// <param name="cancellationToken">Cancellation token.</param>
/// <returns>Prediction result with output URL and metadata.</returns>
Task<PredictionResult> TransformToVideoFromBase64Async(
string base64Image,
string? customPrompt = null,
PredictionOptions? options = null,
CancellationToken cancellationToken = default);
/// <summary>
/// Generate a video from an image URL.
/// </summary>
/// <param name="imageUrl">URL of the image to animate.</param>
/// <param name="customPrompt">Optional custom prompt override.</param>
/// <param name="options">Optional prediction options (webhook, sync mode, etc.).</param>
/// <param name="cancellationToken">Cancellation token.</param>
/// <returns>Prediction result with output URL and metadata.</returns>
Task<PredictionResult> TransformToVideoFromUrlAsync(
string imageUrl,
string? customPrompt = null,
PredictionOptions? options = null,
CancellationToken cancellationToken = default);
/// <summary>
/// Cancel a running prediction.
/// </summary>
/// <param name="predictionId">The prediction ID to cancel.</param>
/// <param name="cancellationToken">Cancellation token.</param>
Task CancelPredictionAsync(string predictionId, CancellationToken cancellationToken = default);
/// <summary>
/// Get the status of a prediction.
/// </summary>
/// <param name="predictionId">The prediction ID to check.</param>
/// <param name="cancellationToken">Cancellation token.</param>
/// <returns>Current prediction status and result if completed.</returns>
Task<PredictionResult> GetPredictionAsync(string predictionId, CancellationToken cancellationToken = default);
/// <summary>
/// Run a prediction using a model preset with image bytes.
/// </summary>
/// <param name="preset">The model preset to use.</param>
/// <param name="imageBytes">The image bytes.</param>
/// <param name="customPrompt">Optional custom prompt override.</param>
/// <param name="customParameters">Optional parameters to override preset defaults.</param>
/// <param name="options">Optional prediction options (webhook, sync mode, etc.).</param>
/// <param name="cancellationToken">Cancellation token.</param>
Task<PredictionResult> RunPresetAsync(
ModelPreset preset,
byte[] imageBytes,
string? customPrompt = null,
Dictionary<string, object>? customParameters = null,
PredictionOptions? options = null,
CancellationToken cancellationToken = default);
/// <summary>
/// Run a prediction using a model preset with base64 image.
/// </summary>
/// <param name="preset">The model preset to use.</param>
/// <param name="base64Image">Base64 encoded image (with or without data URI prefix).</param>
/// <param name="customPrompt">Optional custom prompt override.</param>
/// <param name="customParameters">Optional parameters to override preset defaults.</param>
/// <param name="options">Optional prediction options (webhook, sync mode, etc.).</param>
/// <param name="cancellationToken">Cancellation token.</param>
Task<PredictionResult> RunPresetFromBase64Async(
ModelPreset preset,
string base64Image,
string? customPrompt = null,
Dictionary<string, object>? customParameters = null,
PredictionOptions? options = null,
CancellationToken cancellationToken = default);
/// <summary>
/// Run a prediction using a model preset with image URL.
/// </summary>
/// <param name="preset">The model preset to use.</param>
/// <param name="imageUrl">URL of the image.</param>
/// <param name="customPrompt">Optional custom prompt override.</param>
/// <param name="customParameters">Optional parameters to override preset defaults.</param>
/// <param name="options">Optional prediction options (webhook, sync mode, etc.).</param>
/// <param name="cancellationToken">Cancellation token.</param>
Task<PredictionResult> RunPresetFromUrlAsync(
ModelPreset preset,
string imageUrl,
string? customPrompt = null,
Dictionary<string, object>? customParameters = null,
PredictionOptions? options = null,
CancellationToken cancellationToken = default);
/// <summary>
/// Run a text-only prediction using a model preset (no image input).
/// </summary>
/// <param name="preset">The model preset to use.</param>
/// <param name="prompt">The prompt for generation.</param>
/// <param name="customParameters">Optional parameters to override preset defaults.</param>
/// <param name="options">Optional prediction options (webhook, sync mode, etc.).</param>
/// <param name="cancellationToken">Cancellation token.</param>
Task<PredictionResult> RunPresetTextOnlyAsync(
ModelPreset preset,
string prompt,
Dictionary<string, object>? customParameters = null,
PredictionOptions? options = null,
CancellationToken cancellationToken = default);
}
/// <summary>
/// Options for creating a prediction.
/// </summary>
public class PredictionOptions
{
/// <summary>
/// Webhook URL to receive prediction updates.
/// </summary>
public string? WebhookUrl { get; set; }
/// <summary>
/// Filter which events trigger webhook calls.
/// Options: "start", "output", "logs", "completed"
/// </summary>
public string[]? WebhookEventsFilter { get; set; }
/// <summary>
/// Use sync mode - wait for result up to specified seconds (1-60).
/// If null, uses async mode with polling.
/// </summary>
public int? SyncModeWaitSeconds { get; set; }
/// <summary>
/// If true and using sync mode, don't poll - just return the initial response.
/// Useful when using webhooks.
/// </summary>
public bool WebhookOnly { get; set; }
}
/// <summary>
/// Result of a prediction.
/// </summary>
public class PredictionResult
{
/// <summary>
/// Unique prediction identifier.
/// </summary>
public string Id { get; set; } = string.Empty;
/// <summary>
/// Current status as string: starting, processing, succeeded, failed, canceled.
/// Consider using StatusEnum for type-safe comparisons.
/// </summary>
public string Status { get; set; } = string.Empty;
/// <summary>
/// Current status as a strongly-typed enum.
/// </summary>
public PredictionStatus StatusEnum => Status.ToPredictionStatus();
/// <summary>
/// Output URL(s) if succeeded.
/// </summary>
public string? Output { get; set; }
/// <summary>
/// All output URLs if multiple outputs.
/// </summary>
public string[]? Outputs { get; set; }
/// <summary>
/// Error message if failed.
/// </summary>
public string? Error { get; set; }
/// <summary>
/// Prediction metrics (predict_time, total_time).
/// </summary>
public PredictionMetrics? Metrics { get; set; }
/// <summary>
/// When the prediction was created.
/// </summary>
public DateTimeOffset? CreatedAt { get; set; }
/// <summary>
/// When the prediction started processing.
/// </summary>
public DateTimeOffset? StartedAt { get; set; }
/// <summary>
/// When the prediction completed.
/// </summary>
public DateTimeOffset? CompletedAt { get; set; }
/// <summary>
/// URL to cancel the prediction.
/// </summary>
public string? CancelUrl { get; set; }
/// <summary>
/// Whether the prediction completed (succeeded, failed, or canceled).
/// </summary>
public bool IsCompleted => StatusEnum.IsCompleted();
/// <summary>
/// Whether the prediction succeeded.
/// </summary>
public bool IsSucceeded => StatusEnum == PredictionStatus.Succeeded;
/// <summary>
/// Whether the prediction is pending (starting or processing).
/// </summary>
public bool IsPending => StatusEnum.IsPending();
/// <summary>
/// Whether the prediction failed.
/// </summary>
public bool IsFailed => StatusEnum == PredictionStatus.Failed;
/// <summary>
/// Whether the prediction was canceled.
/// </summary>
public bool IsCanceled => StatusEnum == PredictionStatus.Canceled;
}
/// <summary>
/// Prediction performance metrics.
/// </summary>
public class PredictionMetrics
{
/// <summary>
/// Time spent running the model (seconds).
/// </summary>
public double? PredictTime { get; set; }
/// <summary>
/// Total time including queue wait (seconds).
/// </summary>
public double? TotalTime { get; set; }
}
}