Process (inference api)
  • 20 Aug 2024
  • 8 Minutes to read
  • Dark
    Light

Process (inference api)

  • Dark
    Light

Article summary

CloudFlow Inference API

CloudFlow systems support an inference API similar to on-premises Edgeflows. The major difference is that all transactions with CloudFlow systems use the HTTPS protocol.

POST /1/process/{subject_uid}
HOST: https://<cloudflow-id>.cloudflow.cogniac.io

The URL Prefix for inference requests is composed of the CloudFlow identifier and suffixed with cloudflow.cogniac.io The URL must include the input subject_uid of the first application in a pipeline of applications. This would be an HTTP-Input application type whose configured output subject uid would be the input subject specified in the CloudFlow /1/process inference POST request. An example application flow is shown below.

In the example above, The output subject configured in the HTTP Input app would be the subject_uid specified in the /1/process request.

Additional arguments can be provided as part of the form data as shown in the table below. The HTTPS response includes all detections created by applications that received the image specified in the form data along with the HTTPS status response code.

Argument

Description

Example

image

(required) encoded UTF-8 string representation of the image for inference.


media_timestamp float

(optional) actual timestamp of media creation/occurrence time

1604007056.62

uploaded_by_user string

(optional) user originating request

cloudflow_user@test.ai

domain_unit string

(optional) domain id for set assignment grouping or allowing correlation between groups of images

"test-domain-1

external_media_id string

(optional) arbitrary external id for this media.

"test-external-tracking-993"

custom_data string

(optional) a string of opaque data associated with the input media.

'{'abc': 123, 'test': 'xyz'}'

Responses

Error code

Description

200

Successful completion. Data returned as JSON object.

4xx

401 - Missing Bearer token in the Authorization header  403 - Invalid Bearer token in the Authorization header - refresh the token  404 - Subject ID not found - The output subject uid of the HTTP input application is not configured with the subject uid used in the /1/process call.

5xx

500 - Cannot parse input data - form data incorrect  504 - Backend response timeout - timeout from downstream application(s) - the request took more than 60seconds.  504 - Failed to parse detection - detection format from downstream applications

API Usage Example

API Usage Example using version 2.0.9 and above of the Cogniac SDK. The following steps are required when using the /1/process inference API:

  • Authenticate with Cloudcore

  • Acquire a token from Cloudcore

  • use the token when POSTing a /1/process request to cloud core.

The following example uses the Cogniac Python SDK to simplify the task of authentication and token acquisition. The SDK will simply the authentication, token request, and renewal process in addition to sending a POST request to CloudFlow instance.

from cogniac import CogniacConnection
from time import time
import simplejson as json

TENANT_ID = 'test-tenant-axy'
CLOUDFLOW_ID = 'testfufh7'
FILENAME = 'd1.jpg'
SUBJECT_UID = 'side_view_camera_9lr'

# authenticate with cloudcore and fetch token used in API call
cc = CogniacConnection(tenant_id=TENANT_ID)
ef = cc.get_edgeflow(CLOUDFLOW_ID)

# invoke inference api for subject and image
try:
    resp = ef.process_media(SUBJECT_UID, FILENAME)
    detections = resp['detections']  # list all detections
except Exception as ex:
  pass

An example JSON formatted response is shown below. The primary key is 'detections' whose value is a list of all detections generated by applications downstream from HTTP Input application.

Each detection entry contains the application_id reporting the detection, the model used, output subject_id, probability, and specific application data associated with the application. For example, a box detection app will report app_data_type as 'box_set' and a list of boxes in the app_data dictionary.

{u'detections': [{u'app_data': None,
                  u'app_data_type': None,
                  u'app_id': u'z2PNlsAs',
                  u'assertion_prefix': u'EF:v2p8ckya:NDQIWWPIJI',
                  u'created_at': 1639010302.243763,
                  u'detection_id': u'EF:v2p8ckya:NDQIWWPIJI:1',
                  u'domain_unit': None,
                  u'external_media_id': u'drone_photos_6op-1639010267990000',
                  u'filename': u'LTECFY7OTIUOJFYWGAHKJZ62MQM7-1.jpg',
                  u'focus': None,
                  u'input_subject_association': {u'probability': 1.0,
                                                 u'subject_uid': u'drone_photos_6op'},
                  u'media_md5': u'213a2d9c8d5b53472b8dd555df27ad0b',
                  u'model_id': u'InitialModel_z2PNlsAs_KLHP0K.tgz',
                  u'other_subject_associations': [],
                  u'subject_uid': u'buildings_2sck',
                  u'uncal_prob': 0.0,
                  u'user_id': None},
                 {u'app_data': [{u'box': {u'x0': 826,
                                          u'x1': 907,
                                          u'y0': 653,
                                          u'y1': 689},
                                 u'probability': 0.91015625},      
                                {u'box': {u'x0': 1039,
                                          u'x1': 1083,
                                          u'y0': 214,
                                          u'y1': 324},
                                 u'probability': 0.449462890625}],
                  u'app_data_type': u'box_set',
                  u'app_id': u'kHG1csvg',
                  u'assertion_prefix': u'EF:v2p8ckya:NUFJHOCZKE',
                  u'created_at': 1639010303.168401,
                  u'detection_id': u'EF:v2p8ckya:NUFJHOCZKE:1',
                  u'domain_unit': None,
                  u'external_media_id': u'drone_photos_6op-1639010267990000',
                  u'filename': u'LTECFY7OTIUOJFYWGAHKJZ62MQM7-1.jpg',
                  u'focus': None,
                  u'input_subject_association': {u'probability': 1.0,
                                                 u'subject_uid': u'drone_photos_6op'},
                  u'media_md5': u'213a2d9c8d5b53472b8dd555df27ad0b',
                  u'model_id': u'donor_IVAC_Hpo-d-8e49-DmDT9hhuJLSiFuWOge-YN-OW_mtsv1_INT_10000.tgz',
                  u'other_subject_associations': [],
                  u'subject_uid': u'vehicles_carbox_3gu',
                  u'uncal_prob': 0.91015625,
                  u'user_id': None},                
                 {u'app_data': None,
                  u'app_data_type': None,
                  u'app_id': u'8H88vm4v',
                  u'assertion_prefix': u'EF:v2p8ckya:RITLRGGXGC',
                  u'created_at': 1639010303.297092,
                  u'detection_id': u'EF:v2p8ckya:RITLRGGXGC:11',
                  u'domain_unit': None,
                  u'external_media_id': u'drone_photos_6op-1639010267990000',
                  u'filename': u'LTECFY7OTIUOJFYWGAHKJZ62MQM7-1.jpg',
                  u'focus': {u'box': {u'x0': 1039,
                                      u'x1': 1083,
                                      u'y0': 214,
                                      u'y1': 324}},
                  u'input_subject_association': {u'probability': 0.91015625,
                                                 u'subject_uid': u'vehicles_carbox_3gu'},
                  u'media_md5': u'213a2d9c8d5b53472b8dd555df27ad0b',
                  u'model_id': u'Hpo-m-2d25-KHkIx4sG43EYsU5PzZ-GN-rf_224_224_mtsv1_2.tgz',
                  u'other_subject_associations': [{u'probability': 1.0,
                                                   u'subject_uid': u'drone_photos_6op'}],
                  u'subject_uid': u'vehiclestestoutput_6jo',
                  u'uncal_prob': 3.634687664858485e-23,
                  u'user_id': None}]}

If you are not using the Cogniac Python SDK, an equivalent usage of the /1/process API is shown below. The sample code authenticates via an API key exchanged for a Bearer token.

import requests

TIMEOUT= 5  # Seconds for request to timeout
API_VERSION = 1
CLOUDFLOW_ID = 'your-cloudflow-id'
TENANT_ID = 'your-tenant-id'
SUBJECT_UID = 'your-subject-id'
URL_PREFIX = 'https://%s.cloudflow.cogniac.io/%d/' % (CLOUDFLOW_ID, API_VERSION)
API_KEY = "your-api-key"

class ServerError(Exception):
    """Server timeouts"""

class ClientError(Exception):
    """Unknown local Error"""

class CredentialError(Exception):
    """Expired Credentials"""

def raise_errors(response):
    status = response.status_code
    content = response.content
    if status >= 500:
        raise ServerError("ServerError  (%d): %s" % (status, content))
    elif status in [401, 403]:
        msg = "CredentialError (%d): %s" % (status, content)
        raise CredentialError(msg)
    elif status >= 400:
        msg = "ClientError (%d): %s" % (status, content)
        raise ClientError(msg)
    else:
        pass

def get_auth_headers():
    """
    Swap API key for Bearer token 
    """
    tenant_data = {'tenant_id': TENANT_ID}
    headers = {"Authorization": "Key %s" % API_KEY}
    token_resp = requests.get(
        'https://api.cogniac.io/1' + "/token", 
        params=tenant_data,
        headers=headers,
        timeout=TIMEOUT)
    raise_errors(token_resp)
    token = token_resp.json()
    headers = {"Authorization": "Bearer %s" % token['access_token']}
    return headers

def process_media(filename, subject_uid):
    files = {'file': open(filename, 'rb')}
    headers = get_auth_headers()
    url = URL_PREFIX + 'process/%s' % subject_uid
    resp = requests.post(url, files=files, headers=headers, timeout=TIMEOUT, verify=True)
    raise_errors(resp)
    return resp.json()

if __name__ == '__main__':
    imgfile = 'local/path/to/your/image.jpeg'
    result = process_media(imgfile, SUBJECT_UID)
    print(result)


Was this article helpful?

What's Next