From f76e444f586b0056a4366c0a4528e5a78e0f554f Mon Sep 17 00:00:00 2001 From: David Liang Date: Thu, 11 Jan 2024 18:56:17 +0800 Subject: [PATCH] Customized category / customized model related spec changes (#45) * Add ga contract for Content Safety * Update examples for 2023-10-01 * Resolve ModelValidation SpellCheck and Avocado * Fix typo * Fix minor errors in example and readme * Fix example * remove the 0430 content * update readme * re-format markdowm * Fix example * init content safety 2023-10-15-preview * init content safety 2023-10-15-previwe * update * format example * update read me file * update * update * update contract * update * update * update threshold * update new contract by add judgement kind enum * update description * u * update * updat length * update * update * update description for accept severity threshodl * update * merge with acs-ga * Add snippy contract * remove 8 sev levels for image * update contentsafety.json * Update snippy path * add type spec for jailbreak * Add incident response API in 2023-10-30-preview * compiled * Adaptive annotation service contract * Remove operations * update * update * refine * update * make 0,1,2,3,4,5,6,7 to 0, 1, 2, 3, ... and add comman in last enum value * update path * Update NL Snippy path * Resolve conflict * add * add * remove labelName * Fix route and minor errors * Change typo * update * Update protected material API * update project sample * Change path name * Update protect material contract * update jailbreak * Update incident contract * Update contract * Update * scenarios to enumerations (#19) * Remove project related contract (#20) * Remove project related things * Remove accepted * Remove examples * Merge 1015 (#22) * Add ga contract for Content Safety * Update examples for 2023-10-01 * Resolve ModelValidation SpellCheck and Avocado * Fix typo * Fix minor errors in example and readme * Fix example * remove the 0430 content * update readme * re-format markdowm * Fix example * init content safety 2023-10-15-preview * init content safety 2023-10-15-previwe * update * format example * update read me file * update * update * update contract * update * update * update threshold * update new contract by add judgement kind enum * update description * u * update * updat length * update * update * update description for accept severity threshodl * update * merge with acs-ga * Add snippy contract * remove 8 sev levels for image * update contentsafety.json * Update snippy path * add type spec for jailbreak * compiled * update * update * refine * update * make 0,1,2,3,4,5,6,7 to 0, 1, 2, 3, ... and add comman in last enum value * update path * Update NL Snippy path * Resolve conflict * Update protected material API * update project sample * Change path name * Update protect material contract * update jailbreak * Remove project related contract (#20) * Remove project related things * Remove accepted * Remove examples --------- Co-authored-by: FAREAST\suxi Co-authored-by: Lixiang Liu Co-authored-by: Lixiang Liu Co-authored-by: zhaiyutong * Add list API for Annotation Service (#23) * Add ga contract for Content Safety * Update examples for 2023-10-01 * Resolve ModelValidation SpellCheck and Avocado * Fix typo * Fix minor errors in example and readme * Fix example * remove the 0430 content * update readme * re-format markdowm * Fix example * init content safety 2023-10-15-preview * init content safety 2023-10-15-previwe * update * format example * update read me file * update * update * update contract * update * update * update threshold * update new contract by add judgement kind enum * update description * u * update * updat length * update * update * update description for accept severity threshodl * update * merge with acs-ga * Add snippy contract * remove 8 sev levels for image * update contentsafety.json * Update snippy path * add type spec for jailbreak * compiled * update * update * refine * update * make 0,1,2,3,4,5,6,7 to 0, 1, 2, 3, ... and add comman in last enum value * update path * Update NL Snippy path * Resolve conflict * Update protected material API * update project sample * Change path name * Update protect material contract * update jailbreak * Remove project related contract (#20) * Remove project related things * Remove accepted * Remove examples * Add list category APIs --------- Co-authored-by: FAREAST\suxi Co-authored-by: Lixiang Liu Co-authored-by: Lixiang Liu Co-authored-by: zhaiyutong * Update contract for incident response (#24) Co-authored-by: Lixiang Liu * scenarios to enumerations (#25) * [Cognitive Services - Azure AI Content Safety] - 2023-11-30-preview Private Preview * update doc * resolve comments. * Merge main and recompile swagger * add explanation for 2023-11-30-preview * format * generate swagger * Optimize contract (#36) * add 12-30-preview, add explanation spec * update * renamed reason -> harmful chunks * update. * remove new version enum from GA version * Remove examples from 1015 * restore examples * Add examples for jailbreak and protected material * run prettier for example * commit add enum to stable * Add omit-unreachable-types: true to typespec * compile preview * Fix readme * renamed to citation * UPDATE: add reasoning column and update some docs. * update doc. * update api version. * Fix some typo issues. (#40) * Update data plane. * draft * draft * draft * draft * draft * draft * draft * draft * draft * draft * draft * update bd draft * update spec draft * update spec draft * update spec draft --------- Co-authored-by: mengaims Co-authored-by: FAREAST\suxi Co-authored-by: Lixiang Liu Co-authored-by: Lixiang Liu Co-authored-by: zhaiyutong Co-authored-by: mengaims <50131889+mengaims@users.noreply.github.com> Co-authored-by: YUTONG_ZHAI <32332316+zhaiyutong@users.noreply.github.com> Co-authored-by: Jie Zhou Co-authored-by: Yuxiao Wang Co-authored-by: Yuxiao Wang <58904990+Sayaka-4987@users.noreply.github.com> Co-authored-by: jiezhou_microsoft <94604058+JieZhou000@users.noreply.github.com> Co-authored-by: David Liang --- .../ContentSafety/models.tsp | 92 +++- .../ContentSafety/routes.tsp | 31 ++ .../2023-10-30-preview/contentsafety.json | 5 +- .../2024-01-30-preview/contentsafety.json | 415 +++++++++++++++--- 4 files changed, 490 insertions(+), 53 deletions(-) diff --git a/specification/cognitiveservices/ContentSafety/models.tsp b/specification/cognitiveservices/ContentSafety/models.tsp index 6459f69d9e01..b77017314c13 100644 --- a/specification/cognitiveservices/ContentSafety/models.tsp +++ b/specification/cognitiveservices/ContentSafety/models.tsp @@ -40,6 +40,14 @@ enum AnalyzeImageOutputType { FourSeverityLevels, } +@added(ContentSafety.Versions.v2024_01_30_Preview) +enum ModelStatus { + created, + training, + ready, + failed, +} + @doc("The text analysis request.") model AnalyzeTextOptions { @doc("The text needs to be analyzed. We support a maximum of 10k Unicode characters (Unicode code points) in the text of one request.") @@ -61,6 +69,20 @@ model AnalyzeTextOptions { @added(ContentSafety.Versions.v2023_10_30_Preview) @doc("The incidents to detect.") incidents?: IncidentOptions; + + @added(ContentSafety.Versions.v2024_01_30_Preview) + @doc("The customized categories will be analyzed. If they are not assigned, the analysis results for all available customized categories will be returned.") + customizedCategories?: CustomizedCategory[]; +} + +@added(ContentSafety.Versions.v2024_01_30_Preview) +@doc("Customized category for inference.") +model CustomizedCategory { + @doc("Category name") + categoryName: string; + + @doc("Model ID for the category. If not provided, the latest available model will be used.") + modelId: string; } @added(ContentSafety.Versions.v2023_10_30_Preview) @@ -88,6 +110,28 @@ model AnalyzeTextResult { @added(ContentSafety.Versions.v2024_01_30_Preview) @doc("Chunks in the original text detected as harmful content. Analysis result and scores are caused by these.") citation?: string[]; + + @added(ContentSafety.Versions.v2024_01_30_Preview) + @doc("Analysis result for customized categories.") + customizedCategoriesAnalysis: TextCustomizedCategoryAnalysis[]; +} + +@added(ContentSafety.Versions.v2024_01_30_Preview) +@doc("Text customized category analysis result.") +model TextCustomizedCategoryAnalysis { + @doc("Customized category name") + categoryName: string; + + @doc("customized category analysis") + customizedCategoriesAnalysis: TextCustomizedCategoryClassResult[]; +} + +@added(ContentSafety.Versions.v2024_01_30_Preview) +@doc("customized category analysis result") +model TextCustomizedCategoryClassResult { + id: int32; + @renamedFrom(Versions.v2024_01_30_Preview, "name") + className: string; } @doc("The result of blocklist match.") @@ -456,9 +500,11 @@ model PreDefinedConcept { @added(Versions.v2023_10_30_Preview) @doc("Label definition.") -model SubCategory { +@renamedFrom(Versions.v2024_01_30_Preview, "SubCategory") +model Class { id: int32; - name: string; + @renamedFrom(Versions.v2024_01_30_Preview, "name") + className: string; statements: string[]; } @@ -473,12 +519,39 @@ model TextCustomizedCategory { @maxLength(64) categoryName: string; + @doc("A predefined concept with its definition can be used directly in the subcategories.") + @added(Versions.v2023_10_30_Preview) + @removed(Versions.v2024_01_30_Preview) preDefinedConcepts?: PreDefinedConcept[]; - subCategories: SubCategory[]; + + @doc("Subcategories are detailed classes of the category. It is required there is a class 'safe' with id=0.") + @renamedFrom(Versions.v2024_01_30_Preview, "subCategories") + classes: Class[]; + + @added(Versions.v2023_10_30_Preview) + @removed(Versions.v2024_01_30_Preview) emphases?: string[]; + + @doc("Blob that stores the examples.") exampleBlobUrl?: url; } +@added(ContentSafety.Versions.v2024_01_30_Preview) +@doc("The response for async training triggering.") +model SubmitModelTrainingResponse { + ...AcceptedResponse; + + @header("operation-location") + @doc("The location of the status API for monitoring the triggered model.") + modelUrl: string; +} + +@added(ContentSafety.Versions.v2024_01_30_Preview) +model AsyncJobWarning { + code: string; + messgae: string; +} + #suppress "@azure-tools/typespec-azure-core/documentation-required" "MUST fix in next update" @added(ContentSafety.Versions.v2023_10_30_Preview) @doc("ImageWithText analyze category.") @@ -489,6 +562,19 @@ enum ImageWithTextCategory { Violence, } +@added(ContentSafety.Versions.v2024_01_30_Preview) +@parentResource(TextCustomizedCategory) +@resource("models") +model TextTrainedModel { + @key + modelId: string; + status: ModelStatus; + createdTime: utcDateTime; + lastUpdateTime: utcDateTime; + warnings?: AsyncJobWarning[]; + errors?: string[]; +} + @added(ContentSafety.Versions.v2023_10_30_Preview) @doc("The analysis request of the image with text.") model AnalyzeImageWithTextOptions { diff --git a/specification/cognitiveservices/ContentSafety/routes.tsp b/specification/cognitiveservices/ContentSafety/routes.tsp index 6e0b436297b0..16b36381a21a 100644 --- a/specification/cognitiveservices/ContentSafety/routes.tsp +++ b/specification/cognitiveservices/ContentSafety/routes.tsp @@ -290,6 +290,37 @@ interface TextCategoryCustomization { TextCustomizedCategory, ListQueryParametersTrait >; + + @action("trainModel") + @added(Versions.v2024_01_30_Preview) + trainModel is CategoryOps.ResourceAction< + TextCustomizedCategory, + {}, + SubmitModelTrainingResponse + >; +} + +interface TextCustomizedMdoelOps + extends Azure.Core.ResourceOperations {} + +@added(Versions.v2024_01_30_Preview) +interface TextCustomizedModelOperations { + @summary("List all existing models") + @doc("List existing models.") + listTextCustomizedModels is TextCustomizedMdoelOps.ResourceList< + TextTrainedModel, + ListQueryParametersTrait + >; + + @doc("Get a model that is not deleted.") + getTextCustomizedModels is TextCustomizedMdoelOps.ResourceRead; + + @doc("If the model is training, the training process will be cancelled and the model will also be deleted.") + deleteCustomizedModel is TextCustomizedMdoelOps.ResourceDelete< + TextTrainedModel + >; } @added(Versions.v2023_10_30_Preview) diff --git a/specification/cognitiveservices/data-plane/ContentSafety/preview/2023-10-30-preview/contentsafety.json b/specification/cognitiveservices/data-plane/ContentSafety/preview/2023-10-30-preview/contentsafety.json index f4f32e3af776..9d0aad9dfe01 100644 --- a/specification/cognitiveservices/data-plane/ContentSafety/preview/2023-10-30-preview/contentsafety.json +++ b/specification/cognitiveservices/data-plane/ContentSafety/preview/2023-10-30-preview/contentsafety.json @@ -2931,6 +2931,7 @@ }, "preDefinedConcepts": { "type": "array", + "description": "A predefined concept with its definition can be used directly in the subcategories.", "items": { "$ref": "#/definitions/PreDefinedConcept" }, @@ -2938,6 +2939,7 @@ }, "subCategories": { "type": "array", + "description": "Subcategories are detailed classes of the category. It is required there is a class 'safe' with id=0.", "items": { "$ref": "#/definitions/SubCategory" } @@ -2950,7 +2952,8 @@ }, "exampleBlobUrl": { "type": "string", - "format": "uri" + "format": "uri", + "description": "Blob that stores the examples." } }, "required": [ diff --git a/specification/cognitiveservices/data-plane/ContentSafety/preview/2024-01-30-preview/contentsafety.json b/specification/cognitiveservices/data-plane/ContentSafety/preview/2024-01-30-preview/contentsafety.json index 208f36065325..f1efad653ecf 100644 --- a/specification/cognitiveservices/data-plane/ContentSafety/preview/2024-01-30-preview/contentsafety.json +++ b/specification/cognitiveservices/data-plane/ContentSafety/preview/2024-01-30-preview/contentsafety.json @@ -1055,6 +1055,189 @@ } } }, + "/text/categories/{categoryName}:trainModel": { + "post": { + "operationId": "TextCategoryCustomization_TrainModel", + "description": "Resource action operation template.", + "parameters": [ + { + "$ref": "#/parameters/Azure.Core.Foundations.ApiVersionParameter" + }, + { + "name": "categoryName", + "in": "path", + "description": "Text customizedCategories name.", + "required": true, + "type": "string", + "maxLength": 64, + "pattern": "^Customized_[0-9A-Za-z._~-]+$" + } + ], + "responses": { + "202": { + "description": "The request has been accepted for processing, but processing has not yet completed.", + "headers": { + "operation-location": { + "type": "string", + "description": "The location of the status API for monitoring the triggered model." + } + } + }, + "default": { + "description": "An unexpected error response.", + "schema": { + "$ref": "#/definitions/Azure.Core.Foundations.ErrorResponse" + }, + "headers": { + "x-ms-error-code": { + "type": "string", + "description": "String error code indicating what went wrong." + } + } + } + } + } + }, + "/text/categories/{categoryName}/models": { + "get": { + "operationId": "TextCustomizedModelOperations_ListTextCustomizedModels", + "summary": "List all existing models", + "description": "List existing models.", + "parameters": [ + { + "$ref": "#/parameters/Azure.Core.Foundations.ApiVersionParameter" + }, + { + "name": "categoryName", + "in": "path", + "description": "Text customizedCategories name.", + "required": true, + "type": "string", + "maxLength": 64, + "pattern": "^Customized_[0-9A-Za-z._~-]+$" + }, + { + "$ref": "#/parameters/Azure.Core.TopQueryParameter" + }, + { + "$ref": "#/parameters/Azure.Core.SkipQueryParameter" + }, + { + "$ref": "#/parameters/Azure.Core.MaxPageSizeQueryParameter" + } + ], + "responses": { + "200": { + "description": "The request has succeeded.", + "schema": { + "$ref": "#/definitions/PagedTextTrainedModel" + } + }, + "default": { + "description": "An unexpected error response.", + "schema": { + "$ref": "#/definitions/Azure.Core.Foundations.ErrorResponse" + }, + "headers": { + "x-ms-error-code": { + "type": "string", + "description": "String error code indicating what went wrong." + } + } + } + }, + "x-ms-pageable": { + "nextLinkName": "nextLink" + } + } + }, + "/text/categories/{categoryName}/models/{modelId}": { + "get": { + "operationId": "TextCustomizedModelOperations_GetTextCustomizedModels", + "description": "Get a model that is not deleted.", + "parameters": [ + { + "$ref": "#/parameters/Azure.Core.Foundations.ApiVersionParameter" + }, + { + "name": "categoryName", + "in": "path", + "description": "Text customizedCategories name.", + "required": true, + "type": "string", + "maxLength": 64, + "pattern": "^Customized_[0-9A-Za-z._~-]+$" + }, + { + "name": "modelId", + "in": "path", + "required": true, + "type": "string" + } + ], + "responses": { + "200": { + "description": "The request has succeeded.", + "schema": { + "$ref": "#/definitions/TextTrainedModel" + } + }, + "default": { + "description": "An unexpected error response.", + "schema": { + "$ref": "#/definitions/Azure.Core.Foundations.ErrorResponse" + }, + "headers": { + "x-ms-error-code": { + "type": "string", + "description": "String error code indicating what went wrong." + } + } + } + } + }, + "delete": { + "operationId": "TextCustomizedModelOperations_DeleteCustomizedModel", + "description": "If the model is training, the training process will be cancelled and the model will also be deleted.", + "parameters": [ + { + "$ref": "#/parameters/Azure.Core.Foundations.ApiVersionParameter" + }, + { + "name": "categoryName", + "in": "path", + "description": "Text customizedCategories name.", + "required": true, + "type": "string", + "maxLength": 64, + "pattern": "^Customized_[0-9A-Za-z._~-]+$" + }, + { + "name": "modelId", + "in": "path", + "required": true, + "type": "string" + } + ], + "responses": { + "204": { + "description": "There is no content to send for this request, but the headers may be useful. " + }, + "default": { + "description": "An unexpected error response.", + "schema": { + "$ref": "#/definitions/Azure.Core.Foundations.ErrorResponse" + }, + "headers": { + "x-ms-error-code": { + "type": "string", + "description": "String error code indicating what went wrong." + } + } + } + } + } + }, "/text/incidents": { "get": { "operationId": "TextIncidents_ListIncidents", @@ -1920,6 +2103,14 @@ "incidents": { "$ref": "#/definitions/IncidentOptions", "description": "The incidents to detect." + }, + "customizedCategories": { + "type": "array", + "description": "The customized categories will be analyzed. If they are not assigned, the analysis results for all available customized categories will be returned.", + "items": { + "$ref": "#/definitions/CustomizedCategory" + }, + "x-ms-identifiers": [] } }, "required": [ @@ -2011,10 +2202,19 @@ "items": { "type": "string" } + }, + "customizedCategoriesAnalysis": { + "type": "array", + "description": "Analysis result for customized categories.", + "items": { + "$ref": "#/definitions/TextCustomizedCategoryAnalysis" + }, + "x-ms-identifiers": [] } }, "required": [ - "categoriesAnalysis" + "categoriesAnalysis", + "customizedCategoriesAnalysis" ] }, "AnnotateTextOptions": { @@ -2059,6 +2259,21 @@ "name" ] }, + "AsyncJobWarning": { + "type": "object", + "properties": { + "code": { + "type": "string" + }, + "messgae": { + "type": "string" + } + }, + "required": [ + "code", + "messgae" + ] + }, "Azure.Core.Foundations.Error": { "type": "object", "description": "The error object.", @@ -2120,6 +2335,48 @@ } } }, + "Class": { + "type": "object", + "description": "Label definition.", + "properties": { + "id": { + "type": "integer", + "format": "int32" + }, + "className": { + "type": "string" + }, + "statements": { + "type": "array", + "items": { + "type": "string" + } + } + }, + "required": [ + "id", + "className", + "statements" + ] + }, + "CustomizedCategory": { + "type": "object", + "description": "Customized category for inference.", + "properties": { + "categoryName": { + "type": "string", + "description": "Category name" + }, + "modelId": { + "type": "string", + "description": "Model ID for the category. If not provided, the latest available model will be used." + } + }, + "required": [ + "categoryName", + "modelId" + ] + }, "DetectUngroundednessOptions": { "type": "object", "description": "The request of ungroundedness detection.", @@ -2476,6 +2733,19 @@ "incidentSampleId" ] }, + "ModelStatus": { + "type": "string", + "enum": [ + "created", + "training", + "ready", + "failed" + ], + "x-ms-enum": { + "name": "ModelStatus", + "modelAsString": true + } + }, "PagedImageIncident": { "type": "object", "description": "Paged collection of ImageIncident items", @@ -2630,20 +2900,26 @@ "value" ] }, - "PreDefinedConcept": { + "PagedTextTrainedModel": { "type": "object", - "description": "Pre-defined concept.", + "description": "Paged collection of TextTrainedModel items", "properties": { - "concept": { - "type": "string" + "value": { + "type": "array", + "description": "The TextTrainedModel items on this page", + "items": { + "$ref": "#/definitions/TextTrainedModel" + }, + "x-ms-identifiers": [] }, - "description": { - "type": "string" + "nextLink": { + "type": "string", + "format": "uri", + "description": "The link to the next page of items" } }, "required": [ - "concept", - "description" + "value" ] }, "ProtectedMaterialAnalysisResult": { @@ -2707,30 +2983,6 @@ "incidentSampleIds" ] }, - "SubCategory": { - "type": "object", - "description": "Label definition.", - "properties": { - "id": { - "type": "integer", - "format": "int32" - }, - "name": { - "type": "string" - }, - "statements": { - "type": "array", - "items": { - "type": "string" - } - } - }, - "required": [ - "id", - "name", - "statements" - ] - }, "Task": { "type": "string", "description": "Task type.", @@ -2886,33 +3138,60 @@ "create" ] }, - "preDefinedConcepts": { - "type": "array", - "items": { - "$ref": "#/definitions/PreDefinedConcept" - }, - "x-ms-identifiers": [] - }, - "subCategories": { + "classes": { "type": "array", + "description": "Subcategories are detailed classes of the category. It is required there is a class 'safe' with id=0.", "items": { - "$ref": "#/definitions/SubCategory" + "$ref": "#/definitions/Class" } }, - "emphases": { + "exampleBlobUrl": { + "type": "string", + "format": "uri", + "description": "Blob that stores the examples." + } + }, + "required": [ + "categoryName", + "classes" + ] + }, + "TextCustomizedCategoryAnalysis": { + "type": "object", + "description": "Text customized category analysis result.", + "properties": { + "categoryName": { + "type": "string", + "description": "Customized category name" + }, + "customizedCategoriesAnalysis": { "type": "array", + "description": "customized category analysis", "items": { - "type": "string" + "$ref": "#/definitions/TextCustomizedCategoryClassResult" } - }, - "exampleBlobUrl": { - "type": "string", - "format": "uri" } }, "required": [ "categoryName", - "subCategories" + "customizedCategoriesAnalysis" + ] + }, + "TextCustomizedCategoryClassResult": { + "type": "object", + "description": "customized category analysis result", + "properties": { + "id": { + "type": "integer", + "format": "int32" + }, + "className": { + "type": "string" + } + }, + "required": [ + "id", + "className" ] }, "TextIncident": { @@ -2998,6 +3277,44 @@ "incidentSampleId" ] }, + "TextTrainedModel": { + "type": "object", + "properties": { + "modelId": { + "type": "string" + }, + "status": { + "$ref": "#/definitions/ModelStatus" + }, + "createdTime": { + "type": "string", + "format": "date-time" + }, + "lastUpdateTime": { + "type": "string", + "format": "date-time" + }, + "warnings": { + "type": "array", + "items": { + "$ref": "#/definitions/AsyncJobWarning" + }, + "x-ms-identifiers": [] + }, + "errors": { + "type": "array", + "items": { + "type": "string" + } + } + }, + "required": [ + "modelId", + "status", + "createdTime", + "lastUpdateTime" + ] + }, "UngroundedDetails": { "type": "object", "description": "The detailed information about a text identified as ungrounded.",