Skip to content

Commit

Permalink
Merge pull request #1 from ServiceStack/job-status-refactor
Browse files Browse the repository at this point in the history
Refactor based on discussion about status endpoints and how they shou…
  • Loading branch information
Layoric authored Nov 25, 2024
2 parents 0794300 + 2d56ecb commit c24d30f
Show file tree
Hide file tree
Showing 23 changed files with 263 additions and 202 deletions.
56 changes: 39 additions & 17 deletions AiServer.ServiceInterface/GenerationServices.cs
Original file line number Diff line number Diff line change
Expand Up @@ -9,7 +9,7 @@ namespace AiServer.ServiceInterface;

public class GenerationServices(IBackgroundJobs jobs, AppData appData) : Service
{
public async Task<object> Any(GetJobStatus request)
public async Task<object> Any(GetArtifactGenerationStatus request)
{
JobResult? job = null;
if (request.JobId != null)
Expand All @@ -22,17 +22,17 @@ public async Task<object> Any(GetJobStatus request)
job = jobs.GetJobByRefId(request.RefId);
}

if(job == null || job.Summary.RefId == null)
if(job == null || job.Job == null || job.Summary.RefId == null)
throw HttpError.NotFound("Job not found");

// We know at this point, we definitely have a job
JobResult queuedJob = job;

var completedResponse = new GetJobStatusResponse
var completedResponse = new GetArtifactGenerationStatusResponse
{
RefId = queuedJob.Job?.RefId ?? queuedJob.Summary.RefId,
JobId = queuedJob.Job?.Id ?? queuedJob.Summary.Id,
Status = queuedJob.Job?.Status,
Status = queuedJob.Job?.Status ?? queuedJob.Job!.State.ToString(),
JobState = queuedJob.Job?.State ?? queuedJob.Summary.State
};

Expand All @@ -47,8 +47,7 @@ public async Task<object> Any(GetJobStatus request)

// Process successful job results
var outputs = queuedJob.GetOutputs();
completedResponse.Outputs = outputs.Item1;
completedResponse.TextOutputs = outputs.Item2;
completedResponse.Results = outputs.Item1;

return completedResponse;
}
Expand Down Expand Up @@ -89,7 +88,8 @@ public async Task<object> Any(TextToImage request)
};

await using var diffServices = ResolveService<MediaProviderServices>();
return await diffRequest.ProcessGeneration(jobs, diffServices, sync: true);
var result = await diffRequest.ProcessGeneration(jobs, diffServices, sync: true) as GenerationResponse;
return result.ConvertTo<ArtifactGenerationResponse>();
}

public async Task<object> Any(ImageToImage request)
Expand All @@ -110,7 +110,8 @@ public async Task<object> Any(ImageToImage request)
};

await using var diffServices = ResolveService<MediaProviderServices>();
return await diffRequest.ProcessGeneration(jobs, diffServices, sync: true);
var result = await diffRequest.ProcessGeneration(jobs, diffServices, sync: true) as GenerationResponse;
return result.ConvertTo<ArtifactGenerationResponse>();
}

public async Task<object> Any(ImageUpscale request)
Expand All @@ -127,7 +128,8 @@ public async Task<object> Any(ImageUpscale request)
};

await using var diffServices = ResolveService<MediaProviderServices>();
return await diffRequest.ProcessGeneration(jobs, diffServices, sync: true);
var result = await diffRequest.ProcessGeneration(jobs, diffServices, sync: true) as GenerationResponse;
return result.ConvertTo<ArtifactGenerationResponse>();
}

public async Task<object> Any(ImageWithMask request)
Expand All @@ -148,7 +150,8 @@ public async Task<object> Any(ImageWithMask request)
};

await using var diffServices = ResolveService<MediaProviderServices>();
return await diffRequest.ProcessGeneration(jobs, diffServices, sync: true);
var result = await diffRequest.ProcessGeneration(jobs, diffServices, sync: true) as GenerationResponse;
return result.ConvertTo<ArtifactGenerationResponse>();
}

public async Task<object> Any(ImageToText request)
Expand All @@ -164,7 +167,8 @@ public async Task<object> Any(ImageToText request)
};

await using var diffServices = ResolveService<MediaProviderServices>();
return await diffRequest.ProcessGeneration(jobs, diffServices, sync: true);
var result = await diffRequest.ProcessGeneration(jobs, diffServices, sync: true) as GenerationResponse;
return result.ConvertTo<TextGenerationResponse>();
}
}

Expand Down Expand Up @@ -201,15 +205,15 @@ public static async Task<object> ProcessGeneration(this CreateGeneration diffReq

// Return the job status URL
var jobStatusUrl = AppConfig.Instance.ApplicationBaseUrl.CombineWith(
$"/api/{nameof(GetJobStatus)}?RefId=" + diffResponse.RefId);
$"/api/{nameof(GetArtifactGenerationStatus)}?RefId=" + diffResponse.RefId);

var queueResponse = new QueueGenerationResponse
{
RefId = diffResponse.RefId,
JobId = diffResponse.Id,
Status = queuedJob.Job?.Status,
JobState = queuedJob.Job?.State ?? queuedJob.Summary.State,
StatusUrl = jobStatusUrl
StatusUrl = GetStatusUrl(diffRequest, diffResponse)
};

// Handle failed jobs
Expand All @@ -224,10 +228,7 @@ public static async Task<object> ProcessGeneration(this CreateGeneration diffReq
return queueResponse;
}

var completedResponse = new GenerationResponse()
{

};
var completedResponse = new GenerationResponse { };

// Wait for the job to complete max 1 minute
var timeout = DateTime.UtcNow.AddMinutes(1);
Expand Down Expand Up @@ -262,6 +263,27 @@ public static async Task<object> ProcessGeneration(this CreateGeneration diffReq

return completedResponse;
}

public static string GetStatusUrl(this CreateGeneration request, CreateGenerationResponse response)
{
switch (request.Request.TaskType)
{
case AiTaskType.TextToImage:
case AiTaskType.ImageToImage:
case AiTaskType.ImageUpscale:
case AiTaskType.ImageWithMask:
case AiTaskType.TextToSpeech:
case AiTaskType.TextToAudio:
return AppConfig.Instance.ApplicationBaseUrl.CombineWith(
$"/api/{nameof(GetArtifactGenerationStatus)}?RefId=" + response.RefId);
case AiTaskType.SpeechToText:
case AiTaskType.ImageToText:
return AppConfig.Instance.ApplicationBaseUrl.CombineWith(
$"/api/{nameof(GetTextGenerationStatus)}?RefId=" + response.RefId);
default:
throw new ArgumentOutOfRangeException();
}
}

public static Tuple<List<ArtifactOutput>?,List<TextOutput>?> GetOutputs(this JobResult? job)
{
Expand Down
2 changes: 1 addition & 1 deletion AiServer.ServiceInterface/OpenAiChatServices.cs
Original file line number Diff line number Diff line change
Expand Up @@ -320,7 +320,7 @@ public async Task<object> Get(GetOpenAiChatStatus request)
RefId = request.RefId,
JobState = job.State,
Status = job.State.ToString(),
ChatResponse = chatResponse,
Result = chatResponse,
};
}

Expand Down
6 changes: 3 additions & 3 deletions AiServer.ServiceInterface/VideoServices.cs
Original file line number Diff line number Diff line change
Expand Up @@ -337,7 +337,7 @@ public static async Task<object> ProcessTransform(this CreateMediaTransform medi

// Return the job status URL
var jobStatusUrl = AppConfig.Instance.ApplicationBaseUrl.CombineWith(
$"/api/{nameof(GetJobStatus)}?RefId=" + transformResponse.RefId);
$"/api/{nameof(GetArtifactGenerationStatus)}?RefId=" + transformResponse.RefId);

var queueTransformResponse = new QueueMediaTransformResponse
{
Expand All @@ -360,7 +360,7 @@ public static async Task<object> ProcessTransform(this CreateMediaTransform medi
return queueTransformResponse;
}

var completedResponse = new MediaTransformResponse();
var completedResponse = new ArtifactGenerationResponse();

// Wait for the job to complete max 1 minute
var timeout = DateTime.UtcNow.AddMinutes(1);
Expand All @@ -376,7 +376,7 @@ public static async Task<object> ProcessTransform(this CreateMediaTransform medi

var outputs = queuedJob.GetOutputs();

completedResponse.Outputs = outputs.Item1;
completedResponse.Results = outputs.Item1;
return completedResponse;
}
}
38 changes: 31 additions & 7 deletions AiServer.ServiceModel/Generations.cs
Original file line number Diff line number Diff line change
Expand Up @@ -13,7 +13,7 @@ public class ActiveMediaModels : IGet, IReturn<StringsResponse> {}
[Api("Convert speech to text")]
[Description("Transcribe audio content to text")]
[SystemJson(UseSystemJson.Response)]
public class SpeechToText : IGeneration, IReturn<GenerationResponse>
public class SpeechToText : IGeneration, IReturn<TextGenerationResponse>
{
[ApiMember(Description = "The audio stream containing the speech to be transcribed")]
[Description("The audio stream containing the speech to be transcribed")]
Expand All @@ -35,7 +35,7 @@ public class SpeechToText : IGeneration, IReturn<GenerationResponse>
[Api("Convert text to speech")]
[Description("Generate speech audio from text input")]
[SystemJson(UseSystemJson.Response)]
public class TextToSpeech : IGeneration, IReturn<GenerationResponse>
public class TextToSpeech : IGeneration, IReturn<ArtifactGenerationResponse>
{
[ApiMember(Description = "The text to be converted to speech")]
[Description("The text to be converted to speech")]
Expand Down Expand Up @@ -65,7 +65,7 @@ public class TextToSpeech : IGeneration, IReturn<GenerationResponse>
[Api("Generate image from text description")]
[Description("Create an image based on a text prompt")]
[SystemJson(UseSystemJson.Response)]
public class TextToImage : IGeneration, IReturn<GenerationResponse>
public class TextToImage : IGeneration, IReturn<ArtifactGenerationResponse>
{
[ApiMember(Description = "The main prompt describing the desired image")]
[Description("The main prompt describing the desired image")]
Expand Down Expand Up @@ -116,7 +116,7 @@ public class TextToImage : IGeneration, IReturn<GenerationResponse>
[Api("Generate image from another image")]
[Description("Create a new image based on an existing image and a text prompt")]
[SystemJson(UseSystemJson.Response)]
public class ImageToImage : IGeneration, IReturn<GenerationResponse>
public class ImageToImage : IGeneration, IReturn<ArtifactGenerationResponse>
{
[ApiMember(Description = "The image to use as input")]
[Description("The image to use as input")]
Expand Down Expand Up @@ -168,7 +168,7 @@ public class ImageToImage : IGeneration, IReturn<GenerationResponse>
[Api("Upscale an image")]
[Description("Increase the resolution and quality of an input image")]
[SystemJson(UseSystemJson.Response)]
public class ImageUpscale : IGeneration, IReturn<GenerationResponse>
public class ImageUpscale : IGeneration, IReturn<ArtifactGenerationResponse>
{
[ApiMember(Description = "The image to upscale")]
[Description("The image to upscale")]
Expand All @@ -195,7 +195,7 @@ public class ImageUpscale : IGeneration, IReturn<GenerationResponse>
[Api("Generate image with masked area")]
[Description("Create a new image by applying a mask to an existing image and generating content for the masked area")]
[SystemJson(UseSystemJson.Response)]
public class ImageWithMask : IGeneration, IReturn<GenerationResponse>
public class ImageWithMask : IGeneration, IReturn<ArtifactGenerationResponse>
{
[ApiMember(Description = "Prompt describing the desired output in the masked area")]
[Description("Prompt describing the desired output in the masked area")]
Expand Down Expand Up @@ -244,7 +244,7 @@ public class ImageWithMask : IGeneration, IReturn<GenerationResponse>
[Api("Convert image to text")]
[Description("Extract text content from an image")]
[SystemJson(UseSystemJson.Response)]
public class ImageToText : IGeneration, IReturn<GenerationResponse>
public class ImageToText : IGeneration, IReturn<TextGenerationResponse>
{
[ApiMember(Description = "The image to convert to text")]
[Description("The image to convert to text")]
Expand All @@ -261,6 +261,30 @@ public class ImageToText : IGeneration, IReturn<GenerationResponse>
public string? Tag { get; set; }
}

[Description("Response object for artifact generation requests")]
public class ArtifactGenerationResponse
{
[ApiMember(Description = "List of generated outputs")]
[Description("List of generated outputs")]
public List<ArtifactOutput>? Results { get; set; }

[ApiMember(Description = "Detailed response status information")]
[Description("Detailed response status information")]
public ResponseStatus? ResponseStatus { get; set; }
}

[Description("Response object for text generation requests")]
public class TextGenerationResponse
{
[ApiMember(Description = "List of generated text outputs")]
[Description("List of generated text outputs")]
public List<TextOutput>? Results { get; set; }

[ApiMember(Description = "Detailed response status information")]
[Description("Detailed response status information")]
public ResponseStatus? ResponseStatus { get; set; }
}

[Description("Response object for generation requests")]
public class GenerationResponse
{
Expand Down
37 changes: 10 additions & 27 deletions AiServer.ServiceModel/MediaTransforms.cs
Original file line number Diff line number Diff line change
Expand Up @@ -7,7 +7,7 @@ namespace AiServer.ServiceModel;
[Tag(Tags.Media)]
[Api("Scale video")]
[Description("Scale a video to specified dimensions")]
public class ScaleVideo : IMediaTransform, IReturn<MediaTransformResponse>
public class ScaleVideo : IMediaTransform, IReturn<ArtifactGenerationResponse>
{
[ApiMember(Description = "The video file to be scaled")]
[Description("The video file to be scaled")]
Expand Down Expand Up @@ -38,7 +38,7 @@ public class ScaleVideo : IMediaTransform, IReturn<MediaTransformResponse>
[Tag(Tags.Media)]
[Api("Watermark video")]
[Description("Add a watermark to a video")]
public class WatermarkVideo : IMediaTransform, IReturn<MediaTransformResponse>
public class WatermarkVideo : IMediaTransform, IReturn<ArtifactGenerationResponse>
{
[ApiMember(Description = "The video file to be watermarked")]
[Description("The video file to be watermarked")]
Expand Down Expand Up @@ -78,7 +78,7 @@ public enum WatermarkPosition
[Description("Convert an image to a different format")]
[Tag(Tags.Media)]
[ValidateApiKey]
public class ConvertImage : IMediaTransform, IPost, IReturn<MediaTransformResponse>
public class ConvertImage : IMediaTransform, IPost, IReturn<ArtifactGenerationResponse>
{
[ApiMember(Description = "The image file to be converted")]
[Description("The image file to be converted")]
Expand All @@ -103,7 +103,7 @@ public class ConvertImage : IMediaTransform, IPost, IReturn<MediaTransformRespon
[Description("Crop an image to a specified area")]
[Tag(Tags.Media)]
[ValidateApiKey]
public class CropImage : IMediaTransform, IPost, IReturn<MediaTransformResponse>
public class CropImage : IMediaTransform, IPost, IReturn<ArtifactGenerationResponse>
{
[ApiMember(Description = "The X-coordinate of the top-left corner of the crop area")]
[Description("The X-coordinate of the top-left corner of the crop area")]
Expand Down Expand Up @@ -139,7 +139,7 @@ public class CropImage : IMediaTransform, IPost, IReturn<MediaTransformResponse>
[Description("Scale an image to a specified size")]
[Tag(Tags.Media)]
[ValidateApiKey]
public class ScaleImage : IMediaTransform, IPost, IReturn<MediaTransformResponse>
public class ScaleImage : IMediaTransform, IPost, IReturn<ArtifactGenerationResponse>
{
[ApiMember(Description = "The image file to be scaled")]
[Description("The image file to be scaled")]
Expand Down Expand Up @@ -167,7 +167,7 @@ public class ScaleImage : IMediaTransform, IPost, IReturn<MediaTransformResponse
[Description("Add a watermark to an image")]
[Tag(Tags.Media)]
[ValidateApiKey]
public class WatermarkImage : IMediaTransform, IPost, IReturn<MediaTransformResponse>
public class WatermarkImage : IMediaTransform, IPost, IReturn<ArtifactGenerationResponse>
{
[ApiMember(Description = "The image file to be watermarked")]
[Description("The image file to be watermarked")]
Expand Down Expand Up @@ -199,7 +199,7 @@ public class WatermarkImage : IMediaTransform, IPost, IReturn<MediaTransformResp
[Description("Convert a video to a different format")]
[Tag(Tags.Media)]
[ValidateApiKey]
public class ConvertVideo : IMediaTransform, IReturn<MediaTransformResponse>
public class ConvertVideo : IMediaTransform, IReturn<ArtifactGenerationResponse>
{
[ApiMember(Description = "The desired output format for the converted video")]
[Description("The desired output format for the converted video")]
Expand All @@ -222,7 +222,7 @@ public class ConvertVideo : IMediaTransform, IReturn<MediaTransformResponse>
[Description("Crop a video to a specified area")]
[Tag(Tags.Media)]
[ValidateApiKey]
public class CropVideo : IMediaTransform, IReturn<MediaTransformResponse>
public class CropVideo : IMediaTransform, IReturn<ArtifactGenerationResponse>
{
[ApiMember(Description = "The X-coordinate of the top-left corner of the crop area")]
[Description("The X-coordinate of the top-left corner of the crop area")]
Expand Down Expand Up @@ -264,7 +264,7 @@ public class CropVideo : IMediaTransform, IReturn<MediaTransformResponse>
[Description("Trim a video to a specified duration via start and end times")]
[Tag(Tags.Media)]
[ValidateApiKey]
public class TrimVideo : IMediaTransform, IReturn<MediaTransformResponse>
public class TrimVideo : IMediaTransform, IReturn<ArtifactGenerationResponse>
{
[ApiMember(Description = "The start time of the trimmed video (format: MM:SS)")]
[Description("The start time of the trimmed video (format: MM:SS)")]
Expand All @@ -291,7 +291,7 @@ public class TrimVideo : IMediaTransform, IReturn<MediaTransformResponse>
[Description("Convert an audio file to a different format")]
[Tag(Tags.Media)]
[ValidateApiKey]
public class ConvertAudio : IMediaTransform, IReturn<MediaTransformResponse>
public class ConvertAudio : IMediaTransform, IReturn<ArtifactGenerationResponse>
{
[ApiMember(Description = "The desired output format for the converted audio")]
[Description("The desired output format for the converted audio")]
Expand All @@ -315,21 +315,4 @@ public interface IMediaTransform
{
public string? RefId { get; set; }
public string? Tag { get; set; }
}

[Description("Response object for transform requests")]
public class MediaTransformResponse
{

[ApiMember(Description = "List of generated outputs")]
[Description("List of generated outputs")]
public List<ArtifactOutput>? Outputs { get; set; }

[ApiMember(Description = "List of generated text outputs")]
[Description("List of generated text outputs")]
public List<TextOutput>? TextOutputs { get; set; }

[ApiMember(Description = "Detailed response status information")]
[Description("Detailed response status information")]
public ResponseStatus? ResponseStatus { get; set; }
}
Loading

0 comments on commit c24d30f

Please sign in to comment.