Skip to content
New issue

Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.

By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.

Already on GitHub? Sign in to your account

Azure OpenAI: reuse LRO response model as status polling model #24556

Merged
2 changes: 2 additions & 0 deletions specification/cognitiveservices/OpenAI.Inference/.gitignore
Original file line number Diff line number Diff line change
@@ -0,0 +1,2 @@
**/package.json
**/package-lock.json
10 changes: 7 additions & 3 deletions specification/cognitiveservices/OpenAI.Inference/client.tsp
Original file line number Diff line number Diff line change
Expand Up @@ -3,8 +3,12 @@ import "./main.tsp";

using Azure.ClientGenerator.Core;

// Azure-specific long-running operations should be treated as implementation details
@@internal(Azure.OpenAI.startGenerateImage);
// Azure-specific long-running operations should be treated as implementation details that are wrapped into
// appropriately merged public surface.
@@internal(Azure.OpenAI.beginAzureBatchImageGeneration);
@@internal(Azure.OpenAI.getAzureBatchImageGenerationOperationStatus);

// Some models from client-internal LROs are still desired for custom public surface
// Some models from client-internal LROs are still desired for custom public surface.
@@include(Azure.OpenAI.ImageGenerationOptions);
@@include(Azure.OpenAI.ImageLocation);
@@include(Azure.OpenAI.ImageGenerations);
Original file line number Diff line number Diff line change
@@ -1,5 +1,5 @@
{
"operationId": "GetImageOperationStatus",
"operationId": "GetAzureBatchImageGenerationOperationStatus",
"title": "Returns the status of the images operation",
"parameters": {
"endpoint": "{endpoint}",
Expand Down
Original file line number Diff line number Diff line change
@@ -1,5 +1,5 @@
{
"operationId": "StartGenerateImage",
"operationId": "BeginAzureBatchImageGeneration",
"title": "Starts the generation of a batch of images from a text caption",
"parameters": {
"endpoint": "{endpoint}",
Expand Down
115 changes: 42 additions & 73 deletions specification/cognitiveservices/OpenAI.Inference/models/images.tsp
Original file line number Diff line number Diff line change
@@ -1,6 +1,7 @@
import "@azure-tools/typespec-azure-core";
import "@typespec/http";
import "@typespec/versioning";
import "./operations.common.tsp";

using Azure.Core;
using TypeSpec.Http;
Expand All @@ -21,45 +22,76 @@ enum ImageSize {
Size1024x1024: "1024x1024",
}

@doc("The format in which the generated images are returned.")
@added(ServiceApiVersions.v2023_06_01_Preview)
enum ImageGenerationResponseFormat {
@doc("Image generation response items should provide a URL from which the image may be retrieved.")
Url: "url",

@doc("Image generation response items should provide image data as a base64-encoded string.")
Base64: "b64_json",
}

@doc("Represents the request data used to generate images.")
@added(ServiceApiVersions.v2023_06_01_Preview)
model ImageGenerationOptions {
@doc("A description of the desired images.")
prompt: string;

@doc("The number of images to generate (defaults to 1).")
@projectedName("csharp", "ImageCount")
n?: int32 = 1;

@doc("The desired size of the generated images. Must be one of 256x256, 512x512, or 1024x1024 (defaults to 1024x1024).")
size?: ImageSize = ImageSize.Size1024x1024;

@doc("""
The format in which image generation response items should be presented.
Azure OpenAI only supports URL response items.
""")
@projectedName("json", "response_format")
responseFormat?: ImageGenerationResponseFormat;

@doc("A unique identifier representing your end-user, which can help to monitor and detect abuse.")
user?: string;
}

@doc("The image url if successful, and an error otherwise.")
@doc("An image response item that provides a URL from which an image may be accessed.")
@added(ServiceApiVersions.v2023_06_01_Preview)
@projectedName("csharp", "InternalImageLocation")
model ImageLocation {
@doc("The URL that provides temporary access to download the generated image.")
url?: url;
url: url;
}

@doc("The error if the operation failed.")
error?: Foundations.Error;
@doc("An image response item that directly represents the image data as a base64-encoded string.")
@added(ServiceApiVersions.v2023_06_01_Preview)
model ImagePayload {
@doc("The complete data for an image represented as a base64-encoded string.")
@projectedName("json", "b64_json")
base64Data: string;
}

@doc("The result of the operation if the operation succeeded.")
@added(ServiceApiVersions.v2023_06_01_Preview)
model ImageResponse {
model ImageGenerations {
@doc("A timestamp when this job or item was created (in unix epochs).")
@projectedName("csharp", "InternalCreatedSecondsAfterUnixEpoch")
created: int64;

#suppress "@azure-tools/typespec-autorest/union-unsupported" "openapi v2 not required"
@doc("The images generated by the operator.")
data: ImageLocation[];
@projectedName("csharp", "InternalEmittedImageResponseItems")
data: ImageLocation[] | ImagePayload[];
}

@doc("The result of the operation if the operation succeeded.")
// Note: pending resolution of cross-language code emission behavior for long-running operations, image generation
// reuses its final operation response model as its status polling model.

// @lroStatus
@doc("A polling status update or final response payload for an image operation.")
@added(ServiceApiVersions.v2023_06_01_Preview)
model ImageOperationResponse {
model BatchImageGenerationOperationResponse {
@doc("The ID of the operation.")
id: string;

Expand All @@ -70,74 +102,11 @@ model ImageOperationResponse {
expires?: int64;

@doc("The result of the operation if the operation succeeded.")
result?: ImageResponse;
result?: ImageGenerations;

@doc("The status of the operation")
status: State;
status: AzureOpenAIOperationState;

@doc("The error if the operation failed.")
error?: Foundations.Error;
}

@lroStatus
@doc("The state of a job or item.")
@added(ServiceApiVersions.v2023_06_01_Preview)
enum State {
@doc("The operation was created and is queued to be processed in the future.")
notRunning,

@doc("The operation has started to be processed.")
running,

@lroSucceeded
@doc("The operation has successfully be processed and is ready for consumption.")
succeeded,

@lroCanceled
@doc("The operation has been canceled and is incomplete.")
canceled,

@lroFailed
@doc("The operation has completed processing with a failure and cannot be further consumed.")
failed,
}

@doc("Provides status details for long running operations.")
@added(ServiceApiVersions.v2023_06_01_Preview)
model ImageOperationStatus {
@key("operationId")
@visibility("read", "query")
@doc("The unique ID of the operation.")
id: string;

@doc("The status of the operation")
status: State;
}

#suppress "@azure-tools/typespec-azure-core/long-running-polling-operation-required" "template"
@Foundations.Private.needsRoute
@post
@doc("Long running operation template to match Azure OpenAI .")
op OaiLongRunningRpcOperation<
TParams extends TypeSpec.Reflection.Model,
TResponse extends TypeSpec.Reflection.Model,
TStatusResult extends TypeSpec.Reflection.Model,
TStatusError = Foundations.Error,
Traits extends TypeSpec.Reflection.Model = {},
TErrorResponse = Azure.Core.Foundations.ErrorResponse
> is Foundations.Operation<
TParams &
Azure.Core.Traits.Private.TraitProperties<
Traits,
Azure.Core.Traits.TraitLocation.Parameters
>,
Azure.Core.Foundations.AcceptedResponse &
TResponse &
Foundations.LongRunningStatusLocation<TStatusResult> &
Azure.Core.Traits.Private.TraitProperties<
Traits,
Azure.Core.Traits.TraitLocation.Response
>,
Traits,
TErrorResponse
>;
Original file line number Diff line number Diff line change
@@ -0,0 +1,57 @@
import "@azure-tools/typespec-azure-core";
import "@typespec/http";

using Azure.Core;
using TypeSpec.Http;

namespace Azure.OpenAI;

@lroStatus
@doc("The state of a job or item.")
enum AzureOpenAIOperationState {
@doc("The operation was created and is queued to be processed in the future.")
notRunning,

@doc("The operation has started to be processed.")
running,

@lroSucceeded
@doc("The operation has successfully be processed and is ready for consumption.")
succeeded,

@lroCanceled
@doc("The operation has been canceled and is incomplete.")
canceled,

@lroFailed
@doc("The operation has completed processing with a failure and cannot be further consumed.")
failed,
}

#suppress "@azure-tools/typespec-azure-core/long-running-polling-operation-required" "template"
@Foundations.Private.needsRoute
@post
@doc("Long running operation template to match Azure OpenAI .")
op OaiLongRunningRpcOperation<
TParams extends TypeSpec.Reflection.Model,
TResponse extends TypeSpec.Reflection.Model,
TStatusResult extends TypeSpec.Reflection.Model,
TStatusError = Foundations.Error,
Traits extends TypeSpec.Reflection.Model = {},
TErrorResponse = Azure.Core.Foundations.ErrorResponse
> is Foundations.Operation<
TParams &
Azure.Core.Traits.Private.TraitProperties<
Traits,
Azure.Core.Traits.TraitLocation.Parameters
>,
Azure.Core.Foundations.AcceptedResponse &
TResponse &
Foundations.LongRunningStatusLocation<TStatusResult> &
Azure.Core.Traits.Private.TraitProperties<
Traits,
Azure.Core.Traits.TraitLocation.Response
>,
Traits,
TErrorResponse
>;
15 changes: 9 additions & 6 deletions specification/cognitiveservices/OpenAI.Inference/routes.tsp
Original file line number Diff line number Diff line change
Expand Up @@ -52,29 +52,32 @@ op getChatCompletions is ResourceAction<
ChatCompletions
>;

// Note: pending resolution of cross-language code emission behavior for long-running operations, image generation
// reuses its final operation response model as its status polling model.

#suppress "@azure-tools/typespec-azure-core/no-rpc-path-params" "Allowed because this is a non-standard status polling operation."
@doc("Returns the status of the images operation")
@added(ServiceApiVersions.v2023_06_01_Preview)
@route("/operations/images/{operationId}")
op getImageOperationStatus is RpcOperation<
op getAzureBatchImageGenerationOperationStatus is RpcOperation<
{
@doc(".") @path operationId: string;
},
ImageOperationResponse
BatchImageGenerationOperationResponse
>;

#suppress "@azure-tools/typespec-azure-core/use-standard-operations" ""
@doc("Starts the generation of a batch of images from a text caption")
@added(ServiceApiVersions.v2023_06_01_Preview)
@route("/images/generations:submit")
@pollingOperation(
getImageOperationStatus,
getAzureBatchImageGenerationOperationStatus,
{
operationId: ResponseProperty<"id">,
}
)
op startGenerateImage is OaiLongRunningRpcOperation<
op beginAzureBatchImageGeneration is OaiLongRunningRpcOperation<
ImageGenerationOptions,
ImageOperationResponse,
ImageOperationStatus
BatchImageGenerationOperationResponse,
BatchImageGenerationOperationResponse
>;
Original file line number Diff line number Diff line change
Expand Up @@ -11,28 +11,18 @@ options:
output-file: "{azure-resource-provider-folder}/AzureOpenAI/inference/{version-status}/{version}/generated.json"
azure-resource-provider-folder: "data-plane"
examples-directory: examples
# Uncomment this line and add "@azure-tools/cadl-python" to your package.json to generate Python code
# "@azure-tools/cadl-python":
# "basic-setup-py": true
# "package-version":
# "package-name":
# "output-path":
# Uncomment this line and add "@azure-tools/cadl-java" to your package.json to generate Java code
# "@azure-tools/cadl-java": true
# Uncomment this line and add "@azure-tools/cadl-csharp" to your package.json to generate C# code
omit-unreachable-types: true
"@azure-tools/typespec-csharp":
package-dir: "Azure.AI.OpenAI"
namespace: "Azure.AI.OpenAI"
clear-output-folder: true
model-namespace: false
# https://github.com/Azure/azure-rest-api-specs/issues/24497
"@azure-tools/typespec-java":
package-dir: "azure-ai-openai"
namespace: "com.azure.ai.openai"
partial-update: true
enable-sync-stack: true
generate-tests: false
# https://github.com/Azure/azure-rest-api-specs/issues/24498
# "@azure-tools/typespec-ts":
# package-dir: "azure-ai-openai"
# emitter-output-dir: "{project-root}/generated"
Expand Down
Original file line number Diff line number Diff line change
@@ -1,5 +1,5 @@
{
"operationId": "GetImageOperationStatus",
"operationId": "GetAzureBatchImageGenerationOperationStatus",
"title": "Returns the status of the images operation",
"parameters": {
"endpoint": "{endpoint}",
Expand Down
Original file line number Diff line number Diff line change
@@ -1,5 +1,5 @@
{
"operationId": "StartGenerateImage",
"operationId": "BeginAzureBatchImageGeneration",
"title": "Starts the generation of a batch of images from a text caption",
"parameters": {
"endpoint": "{endpoint}",
Expand Down
Loading