- 20 Aug 2024
- 8 Minutes to read
- Print
- DarkLight
Process (inference api)
- Updated on 20 Aug 2024
- 8 Minutes to read
- Print
- DarkLight
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)