Skip to content

Commit

Permalink
Migrate existing Azure AI Face service to TypeSpec (#27576)
Browse files Browse the repository at this point in the history
* Add following operations:
- Liveness Session
- Person Directory
- Person Group
- Face List
- Face Operations

* Restructure and rename operations
Omit unreachable types

* Change PD to non-LRO

* Update example, doc, data decorator and unnecessary sharedRoute

* Use union to represent extensible enum
Add suppressions
Add default value for models
Fix age type
Rename model in sdk

Refine examples and train headers

Add uuid type, groupId type and name min length

Use our own operation state

Change liveness operation to enum

Refine group id pattern

Use array for csv fields

Separate request and response model for collection

Flatten interface

Flatten parameter for more interface

* Mark detect as internal for customization

* Add liveness audit response schema

* Update documents (add and fix description format and add examples)

Co-authored-by: Shawn Lin <Shao.Lin@microsoft.com>

* Move path to host template

* Move suppression to config

Fix format and suppress response code failure

Fix breaking changes

Switch endpoint to uri

Refine liveness session model

Move away from standard operation to use our own error code

* Set liveness with verify session as internal

* Remove 4xx examples for now with some document updates (#4)

* Update detection document

* Update 4xx examples

* Update example parameter and response

* Several doc fix for PD

* Differenct recognition descriptions for different data structure

* Fix bullet points in note and update some PD doc

* Update liveness doc

* Remove 4xx examples for now to pass validation

---------

Co-authored-by: Shawn Lin <Shao.Lin@microsoft.com>
Co-authored-by: Shawn Lin <shaoli@microsoft.com>

* Add verify image response in create session

* Rename API operation name (#5)

* Change document to new operation names

* Rename

* More renaming

---------

Co-authored-by: Shawn Lin <Shao.Lin@microsoft.com>
Co-authored-by: Shawn Lin <shaoli@microsoft.com>

* Refine verify image header description

* Add partial update for java

* Use shared route for DPG LRO
Use original LRO for PD person and face creation

* Use resource decorator instead of specify resource in LRO response

* Change name for patch to optional

* Correct operation status name
Correct DPG example

* Rename operation status model

* Correct operation result example

* Add gated attribute

* Fix validation

* Force public model for internal detect

* Correct update DPG model

* Disable detect from url convenientAPI for java

* Rename dpg write

* Fix comment

* Rename id and remove customized uuid

* Correct access level of landmark and attribute

* Correct more models' access

* Collect client customization into client.tsp

* Correct verify pd parameter type

* Correct type

* Reorder detect parameters

* Rename session model

* Refine description for return reco model

* Remove detection convenient API

* Add link of error code and message (#6)

Co-authored-by: Shawn Lin <Shao.Lin@microsoft.com>

* Fix validation

* Remove unnecessary model

* Rename model

* Remove redundant line

---------

Co-authored-by: Han Chiang <hachiang@microsoft.com>
Co-authored-by: shaoli-msft <165001074+shaoli-msft@users.noreply.github.com>
Co-authored-by: Shawn Lin <Shao.Lin@microsoft.com>
Co-authored-by: Shawn Lin <shaoli@microsoft.com>
  • Loading branch information
5 people authored Apr 30, 2024
1 parent b8af2fc commit 241c4f0
Show file tree
Hide file tree
Showing 221 changed files with 17,091 additions and 4 deletions.
10 changes: 9 additions & 1 deletion cSpell.json
Original file line number Diff line number Diff line change
Expand Up @@ -1241,7 +1241,7 @@
"WSUS"
]
},
{
{
"filename": "**/specification/monitor/resource-manager/Microsoft.Insights/**/actionGroups_API.json",
"words": [
"occurringlocation",
Expand All @@ -1251,6 +1251,14 @@
"tsgid",
"correlationid"
]
},
{
"filename": "**/specification/ai/data-plane/Face/**/*.json",
"words": [
"headwear",
"realface",
"spoofface"
]
}
],
"enableFiletypes": [
Expand Down
193 changes: 193 additions & 0 deletions specification/ai/Face/client.tsp
Original file line number Diff line number Diff line change
@@ -0,0 +1,193 @@
import "@azure-tools/typespec-client-generator-core";
import "@typespec/rest";
import "@typespec/http";
import "@typespec/versioning";
import "./main.tsp";

using Azure.ClientGenerator.Core;
using Face;

@TypeSpec.Versioning.useDependency(Azure.Core.Versions.v1_0_Preview_2)
@TypeSpec.Versioning.useDependency(Face.Versions.v1_1_preview_1)
namespace ClientCustomizations;

@@clientName(RecognitionModel, "FaceRecognitionModel");
@@clientName(DetectionModel, "FaceDetectionModel");
@@clientName(OperationStatus, "FaceOperationStatus");
@@clientName(TrainingResult, "FaceCollectionTrainingResult");
@@clientName(IdentificationResult, "FaceIdentificationResult");
@@clientName(IdentificationCandidate, "FaceIdentificationCandidate");
@@clientName(VerificationResult, "FaceVerificationResult");
@@clientName(FindSimilarResult, "FaceFindSimilarResult");
@@clientName(GroupingResult, "FaceGroupingResult");
@@clientName(OperationResult, "FaceOperationResult");
@@clientName(LivenessDecision, "FaceLivenessDecision");
@@clientName(ImageType, "FaceImageType");

@@access(FaceAttributeType, Access.public);
@@access(FaceDetectionResult, Access.public);
@@access(FaceLandmarks, Access.public);
@@access(LandmarkCoordinate, Access.public);
@@access(FaceAttributes, Access.public);
@@access(FacialHair, Access.public);
@@access(GlassesType, Access.public);
@@access(HeadPose, Access.public);
@@access(HairProperties, Access.public);
@@access(HairColor, Access.public);
@@access(HairColorType, Access.public);
@@access(OcclusionProperties, Access.public);
@@access(AccessoryItem, Access.public);
@@access(AccessoryType, Access.public);
@@access(BlurProperties, Access.public);
@@access(BlurLevel, Access.public);
@@access(ExposureProperties, Access.public);
@@access(ExposureLevel, Access.public);
@@access(NoiseProperties, Access.public);
@@access(NoiseLevel, Access.public);
@@access(MaskProperties, Access.public);
@@access(MaskType, Access.public);
@@access(QualityForRecognition, Access.public);
@@access(CreateLivenessWithVerifySessionResult, Access.public);

@client({
name: "FaceClient",
service: Face,
})
interface FaceClient {
@access(Access.internal)
@convenientAPI(false, "java")
@convenientAPI(false, "csharp")
detectFromUrl is FaceDetectionOperations.detectFromUrl;
#suppress "@azure-tools/typespec-azure-core/byos" "It's an RPC call to detect face from an image, it doesn't store anything. There's a BYOS version of this call, but it's not this one."
@access(Access.internal)
@convenientAPI(false, "java")
@convenientAPI(false, "csharp")
detect is FaceDetectionOperations.detect;

findSimilar is FaceRecognitionOperations.findSimilar;
findSimilarFromFaceList is FaceRecognitionOperations.findSimilarFromFaceList;
findSimilarFromLargeFaceList is FaceRecognitionOperations.findSimilarFromLargeFaceList;
identifyFromPersonGroup is FaceRecognitionOperations.identifyFromPersonGroup;
identifyFromLargePersonGroup is FaceRecognitionOperations.identifyFromLargePersonGroup;
identifyFromPersonDirectory is FaceRecognitionOperations.identifyFromPersonDirectory;
identifyFromDynamicPersonGroup is FaceRecognitionOperations.identifyFromDynamicPersonGroup;
verifyFaceToFace is FaceRecognitionOperations.verifyFaceToFace;
verifyFromPersonGroup is FaceRecognitionOperations.verifyFromPersonGroup;
verifyFromLargePersonGroup is FaceRecognitionOperations.verifyFromLargePersonGroup;
verifyFromPersonDirectory is FaceRecognitionOperations.verifyFromPersonDirectory;
group is FaceRecognitionOperations.group;
}

@client({
name: "FaceAdministrationClient",
service: Face,
})
interface FaceAdministrationClient {
createFaceList is FaceListOperations.createFaceList;
deleteFaceList is FaceListOperations.deleteFaceList;
getFaceList is FaceListOperations.getFaceList;
updateFaceList is FaceListOperations.updateFaceList;
getFaceLists is FaceListOperations.getFaceLists;
addFaceListFaceFromUrl is FaceListOperations.addFaceListFaceFromUrl;
#suppress "@azure-tools/typespec-azure-core/byos" "It's an RPC call to detect face from an image, it doesn't store anything. There's a BYOS version of this call, but it's not this one."
addFaceListFace is FaceListOperations.addFaceListFace;
deleteFaceListFace is FaceListOperations.deleteFaceListFace;

createLargeFaceList is FaceListOperations.createLargeFaceList;
deleteLargeFaceList is FaceListOperations.deleteLargeFaceList;
getLargeFaceList is FaceListOperations.getLargeFaceList;
updateLargeFaceList is FaceListOperations.updateLargeFaceList;
getLargeFaceLists is FaceListOperations.getLargeFaceLists;
getLargeFaceListTrainingStatus is FaceListOperations.getLargeFaceListTrainingStatus;
trainLargeFaceList is FaceListOperations.trainLargeFaceList;
addLargeFaceListFaceFromUrl is FaceListOperations.addLargeFaceListFaceFromUrl;
#suppress "@azure-tools/typespec-azure-core/byos" "It's an RPC call to detect face from an image, it doesn't store anything. There's a BYOS version of this call, but it's not this one."
addLargeFaceListFace is FaceListOperations.addLargeFaceListFace;
deleteLargeFaceListFace is FaceListOperations.deleteLargeFaceListFace;
getLargeFaceListFace is FaceListOperations.getLargeFaceListFace;
updateLargeFaceListFace is FaceListOperations.updateLargeFaceListFace;
getLargeFaceListFaces is FaceListOperations.getLargeFaceListFaces;

createPersonGroup is PersonGroupOperations.createPersonGroup;
deletePersonGroup is PersonGroupOperations.deletePersonGroup;
getPersonGroup is PersonGroupOperations.getPersonGroup;
updatePersonGroup is PersonGroupOperations.updatePersonGroup;
getPersonGroups is PersonGroupOperations.getPersonGroups;
getPersonGroupTrainingStatus is PersonGroupOperations.getPersonGroupTrainingStatus;
trainPersonGroup is PersonGroupOperations.trainPersonGroup;
createPersonGroupPerson is PersonGroupOperations.createPersonGroupPerson;
deletePersonGroupPerson is PersonGroupOperations.deletePersonGroupPerson;
getPersonGroupPerson is PersonGroupOperations.getPersonGroupPerson;
updatePersonGroupPerson is PersonGroupOperations.updatePersonGroupPerson;
getPersonGroupPersons is PersonGroupOperations.getPersonGroupPersons;
addPersonGroupPersonFaceFromUrl is PersonGroupOperations.addPersonGroupPersonFaceFromUrl;
#suppress "@azure-tools/typespec-azure-core/byos" "It's an RPC call to detect face from an image, it doesn't store anything. There's a BYOS version of this call, but it's not this one."
addPersonGroupPersonFace is PersonGroupOperations.addPersonGroupPersonFace;
deletePersonGroupPersonFace is PersonGroupOperations.deletePersonGroupPersonFace;
getPersonGroupPersonFace is PersonGroupOperations.getPersonGroupPersonFace;
updatePersonGroupPersonFace is PersonGroupOperations.updatePersonGroupPersonFace;

createLargePersonGroup is PersonGroupOperations.createLargePersonGroup;
deleteLargePersonGroup is PersonGroupOperations.deleteLargePersonGroup;
getLargePersonGroup is PersonGroupOperations.getLargePersonGroup;
updateLargePersonGroup is PersonGroupOperations.updateLargePersonGroup;
getLargePersonGroups is PersonGroupOperations.getLargePersonGroups;
getLargePersonGroupTrainingStatus is PersonGroupOperations.getLargePersonGroupTrainingStatus;
trainLargePersonGroup is PersonGroupOperations.trainLargePersonGroup;
createLargePersonGroupPerson is PersonGroupOperations.createLargePersonGroupPerson;
deleteLargePersonGroupPerson is PersonGroupOperations.deleteLargePersonGroupPerson;
getLargePersonGroupPerson is PersonGroupOperations.getLargePersonGroupPerson;
updateLargePersonGroupPerson is PersonGroupOperations.updateLargePersonGroupPerson;
getLargePersonGroupPersons is PersonGroupOperations.getLargePersonGroupPersons;
addLargePersonGroupPersonFaceFromUrl is PersonGroupOperations.addLargePersonGroupPersonFaceFromUrl;
#suppress "@azure-tools/typespec-azure-core/byos" "It's an RPC call to detect face from an image, it doesn't store anything. There's a BYOS version of this call, but it's not this one."
addLargePersonGroupPersonFace is PersonGroupOperations.addLargePersonGroupPersonFace;
deleteLargePersonGroupPersonFace is PersonGroupOperations.deleteLargePersonGroupPersonFace;
getLargePersonGroupPersonFace is PersonGroupOperations.getLargePersonGroupPersonFace;
updateLargePersonGroupPersonFace is PersonGroupOperations.updateLargePersonGroupPersonFace;

createPerson is PersonDirectoryOperations.createPerson;
deletePerson is PersonDirectoryOperations.deletePerson;
getPerson is PersonDirectoryOperations.getPerson;
updatePerson is PersonDirectoryOperations.updatePerson;
getPersons is PersonDirectoryOperations.getPersons;
getDynamicPersonGroupReferences is PersonDirectoryOperations.getDynamicPersonGroupReferences;
addPersonFaceFromUrl is PersonDirectoryOperations.addPersonFaceFromUrl;
#suppress "@azure-tools/typespec-azure-core/byos" "It's an RPC call to detect face from an image, it doesn't store anything. There's a BYOS version of this call, but it's not this one."
addPersonFace is PersonDirectoryOperations.addPersonFace;
deletePersonFace is PersonDirectoryOperations.deletePersonFace;
getPersonFace is PersonDirectoryOperations.getPersonFace;
updatePersonFace is PersonDirectoryOperations.updatePersonFace;
getPersonFaces is PersonDirectoryOperations.getPersonFaces;

createDynamicPersonGroupWithPerson is PersonDirectoryOperations.createDynamicPersonGroupWithPerson;
createDynamicPersonGroup is PersonDirectoryOperations.createDynamicPersonGroup;
deleteDynamicPersonGroup is PersonDirectoryOperations.deleteDynamicPersonGroup;
getDynamicPersonGroup is PersonDirectoryOperations.getDynamicPersonGroup;
updateDynamicPersonGroupWithPersonChanges is PersonDirectoryOperations.updateDynamicPersonGroupWithPersonChanges;
updateDynamicPersonGroup is PersonDirectoryOperations.updateDynamicPersonGroup;
getDynamicPersonGroups is PersonDirectoryOperations.getDynamicPersonGroups;
getDynamicPersonGroupPersons is PersonDirectoryOperations.getDynamicPersonGroupPersons;
}

@client({
name: "FaceSessionClient",
service: Face,
})
interface FaceSessionClient {
createLivenessSession is LivenessSessionOperations.createLivenessSession;
deleteLivenessSession is LivenessSessionOperations.deleteLivenessSession;
getLivenessSessionResult is LivenessSessionOperations.getLivenessSessionResult;
getLivenessSessions is LivenessSessionOperations.getLivenessSessions;
getLivenessSessionAuditEntries is LivenessSessionOperations.getLivenessSessionAuditEntries;

@access(Access.internal)
createLivenessWithVerifySession is LivenessSessionOperations.createLivenessWithVerifySession;
#suppress "@azure-tools/typespec-azure-core/byos" "It's an RPC call to detect face from an image, it doesn't store anything. There's a BYOS version of this call, but it's not this one."
@access(Access.internal)
createLivenessWithVerifySessionWithVerifyImage is LivenessSessionOperations.createLivenessWithVerifySessionWithVerifyImage;
deleteLivenessWithVerifySession is LivenessSessionOperations.deleteLivenessWithVerifySession;
getLivenessWithVerifySessionResult is LivenessSessionOperations.getLivenessWithVerifySessionResult;
getLivenessWithVerifySessions is LivenessSessionOperations.getLivenessWithVerifySessions;
getLivenessWithVerifySessionAuditEntries is LivenessSessionOperations.getLivenessWithVerifySessionAuditEntries;
}
181 changes: 181 additions & 0 deletions specification/ai/Face/examples/v1.1-preview.1/Detect.json
Original file line number Diff line number Diff line change
@@ -0,0 +1,181 @@
{
"title": "Detect with Image",
"operationId": "FaceDetectionOperations_Detect",
"parameters": {
"apiVersion": "v1.1-preview.1",
"returnFaceId": true,
"returnFaceLandmarks": true,
"returnFaceAttributes": "glasses,headPose,occlusion,accessories,blur,exposure,noise,qualityForRecognition",
"recognitionModel": "recognition_03",
"returnRecognitionModel": true,
"detectionModel": "detection_01",
"faceIdTimeToLive": 60,
"imageContent": "<your-image-bytes-here>"
},
"responses": {
"200": {
"body": [
{
"faceId": "c5c24a82-6845-4031-9d5d-978df9175426",
"recognitionModel": "recognition_03",
"faceRectangle": {
"width": 78,
"height": 78,
"left": 394,
"top": 54
},
"faceLandmarks": {
"pupilLeft": {
"x": 412.7,
"y": 78.4
},
"pupilRight": {
"x": 446.8,
"y": 74.2
},
"noseTip": {
"x": 437.7,
"y": 92.4
},
"mouthLeft": {
"x": 417.8,
"y": 114.4
},
"mouthRight": {
"x": 451.3,
"y": 109.3
},
"eyebrowLeftOuter": {
"x": 397.9,
"y": 78.5
},
"eyebrowLeftInner": {
"x": 425.4,
"y": 70.5
},
"eyeLeftOuter": {
"x": 406.7,
"y": 80.6
},
"eyeLeftTop": {
"x": 412.2,
"y": 76.2
},
"eyeLeftBottom": {
"x": 413.0,
"y": 80.1
},
"eyeLeftInner": {
"x": 418.9,
"y": 78.0
},
"eyebrowRightInner": {
"x": 4.8,
"y": 69.7
},
"eyebrowRightOuter": {
"x": 5.5,
"y": 68.5
},
"eyeRightInner": {
"x": 441.5,
"y": 75.0
},
"eyeRightTop": {
"x": 446.4,
"y": 71.7
},
"eyeRightBottom": {
"x": 447.0,
"y": 75.3
},
"eyeRightOuter": {
"x": 451.7,
"y": 73.4
},
"noseRootLeft": {
"x": 428.0,
"y": 77.1
},
"noseRootRight": {
"x": 435.8,
"y": 75.6
},
"noseLeftAlarTop": {
"x": 428.3,
"y": 89.7
},
"noseRightAlarTop": {
"x": 442.2,
"y": 87.0
},
"noseLeftAlarOutTip": {
"x": 424.3,
"y": 96.4
},
"noseRightAlarOutTip": {
"x": 446.6,
"y": 92.5
},
"upperLipTop": {
"x": 437.6,
"y": 105.9
},
"upperLipBottom": {
"x": 437.6,
"y": 108.2
},
"underLipTop": {
"x": 436.8,
"y": 111.4
},
"underLipBottom": {
"x": 437.3,
"y": 114.5
}
},
"faceAttributes": {
"glasses": "sunglasses",
"headPose": {
"roll": 2.1,
"yaw": 3,
"pitch": 1.6
},
"occlusion": {
"foreheadOccluded": false,
"eyeOccluded": false,
"mouthOccluded": false
},
"accessories": [
{
"type": "headwear",
"confidence": 0.99
},
{
"type": "glasses",
"confidence": 1.0
},
{
"type": "mask",
"confidence": 0.87
}
],
"blur": {
"blurLevel": "medium",
"value": 0.51
},
"exposure": {
"exposureLevel": "goodExposure",
"value": 0.55
},
"noise": {
"noiseLevel": "low",
"value": 0.12
},
"qualityForRecognition": "high"
}
}
]
}
}
}
Loading

0 comments on commit 241c4f0

Please sign in to comment.