Sending Inferences

Once you have uploaded your model, you can start sending inferences to Arthur. Inferences sent should match the schema returned by ArthurModel.review(). In addition to your model attributes, a unique id (partner_inference_id), timestamp (inference_timestamp) can be included, but if you leave them out we’ll generate them for you. If your model is a batch model, you must also include a batch_id.

Note that partner_inference_id is the matching mechanism for sending ground truth later after prediction.

All timestamps should be timezone-aware, either as an ISO-8601 string or as datetime objects in your Pandas DataFrame or Parquet files.

Send Inferences

To send fewer than 100,000 rows of data at a time, we recommend using the ArthurModel.send_inferences() method.

For example:

inferences_df = X_test.copy()

predictions = sklearn_model.predict_proba(X_test)
inferences_df["prediction_not_creditworthy"] = predictions[:, 0]
inferences_df["prediction_is_creditworthy"] = predictions[:, 1]

inferences_df["ground_truth_is_creditworthy"] = y_test
inferences_df["ground_truth_not_creditworthy"] = 1 - y_test

result = arthur_model.send_inferences(inferences_df)

If your model is configured as a batch model, you can simply include a batch_id in the last call:

arthur_model.send_inferences(inferences_df, batch_id="batch_1")

You can also send ground truth data separately from inference data if it is not available until later:

inferences_df = X_test.copy()
predictions = sklearn_model.predict_proba(X_test)

inferences_df["prediction_not_creditworthy"] = predictions[:, 0]
inferences_df["prediction_is_creditworthy"] = predictions[:, 1]

batch_id = "batch_1"
inference_ids = [f"{batch_id}-inf_{i}" for i in range(len(inferences_df))]

inf_response = arthur_model.send_inferences(inferences_df, partner_inference_ids=inference_ids)

ground_truth_data = {"ground_truth_is_creditworthy": y_test,
                     "ground_truth_not_creditworthy": 1 - y_test}

gt_response = arthur_model.update_inference_ground_truths(ground_truth_data,
                                                          partner_inference_ids=inference_ids)

Send Inferences At Scale

To send more than 100,000 or more rows, we recommend using the ArthurModel.send_bulk_inferences() method. For bulk inferences, ground truth and inference data must be sent separately and joined on your partner_inference_id.

inferences_df = X_test.copy()

predictions = sklearn_model.predict_proba(X_test)
inferences_df["prediction_not_creditworthy"] = predictions[:, 0]
inferences_df["prediction_is_creditworthy"] = predictions[:, 1]

ground_truth_df = pd.DataFrame({'ground_truth_is_creditworthy': y_test,
                                'ground_truth_not_creditworthy': 1 - y_test})

batch_id = "batch_1"
partner_inference_ids = [f"{batch_id}-inf_{i}" for i in range(len(inferences_df))]

inferences_df["partner_inference_id"] = partner_inference_ids
ground_truth_df["partner_inference_id"] = partner_inference_ids

arthur_model.send_bulk_inferences(data=inferences_df, batch_id=batch_id)
arthur_model.send_bulk_ground_truth(data=inferences_df, batch_id=batch_id)

Sending Parquet Files

If your typical batches are larger than might fit in memory, you can specify a directory containing parquet files to upload a batch for either predictions or ground truth.

arthur_model.send_batch_inferences(directory_path='./data/batch_inference_files/', batch_id="batch_1")
arthur_model.send_bulk_inferences(directory_path='./data/batch_inference_files/', batch_id="batch1")

Sending A Stream of Inferences

You can also send your inferences one at a time:

model_pipeline_input = {
    "Zip": "30144",
    "Home Value": 144000,
    "Liquid Resources": 2,
    "Investment Resources": 1,
}
predicted_value = {
    "Consumer Credit Score": 644.3
}
partner_inference_id = "1"

arthur_model.send_inference(
    inference_timestamp = datetime.datetime.now(pytz.utc),   # must be timezone aware
    partner_inference_id = partner_inference_id,
    model_pipeline_input = model_pipeline_input,
    predicted_value = predicted_value
    )

Sending Inferences for Computer Vision Models

Computer Vision models (any model where input_type == InputType.Image) require the same structure as Tabular/NLP models. However a couple things to note:

  • The attribute value for Image attributes should be a valid path to the image file for that inference.

  • If using an Object Detection model, bounding boxes should be formatted as lists in the form [class_id, confidence, top_left_x, top_left_y, width, height]

So using the following model as an example:

	name	            stage	           value_type	
0	image	            PIPELINE_INPUT	   IMAGE	
1	label	            GROUND_TRUTH	   BOUNDING_BOX
2	objects_detected	PREDICTED_VALUE	   BOUNDING_BOX	

a valid inference dictionary would look like

inference = {
        "partner_inference_id": str(uuid.uuid4()),
        "inference_timestamp": datetime.now(pytz.utc),
        "inference_data": {
            "image": "data/validation/img_0098.png",
            "objects_detected": [
                [0, 0.98, 12, 20, 50, 25],
                [1, 0.22, 4, 5, 14, 32],
                [1, 0.89, 23, 45, 45, 21]
            ]
        },
        "ground_truth_timestamp": datetime.now(pytz.utc),
        "ground_truth_data": {
            "label": [
                [0, 1, 14, 22, 48, 29],
                [1, 1, 25, 43, 49, 25]
            ]
        }
    
}

arthur_model.send_bulk_ground_truths(data=ground_truth)

You can also sending image inferences in batches - using parquet files, or passing in a dataframe.