<jupyter_start><jupyter_text>Serve the autoencoder and detect anomalous credit card activity ![overview-5.png](./images/overview-5.png)  Query Model Repository for best mnist Model<jupyter_code>from hops import model
from hops.model import Metric
MODEL_NAME="ccfraudmodel"
EVALUATION_METRIC="loss"
best_model = model.get_best_model(MODEL_NAME, EVALUATION_METRIC, Metric.MIN)
print('Model name: ' + best_model['name'])
print('Model version: ' + str(best_model['version']))
print(best_model['metrics'])<jupyter_output>Model name: ccfraudmodel
Model version: 1
{'loss': '1.74222993850708'}<jupyter_text>Create Model Serving of Exported Model<jupyter_code>from hops import serving
from hops import hdfs
TOPIC_NAME = "credit_card_prediction_logs"

SERVING_NAME = MODEL_NAME
MODEL_PATH="/Models/" + best_model['name']
TRANSFORMER_PATH = "/Projects/" + hdfs.project_name() + "/Jupyter/card_activity_transformer.py"

response = serving.create_or_update(SERVING_NAME, MODEL_PATH, model_version=best_model['version'], artifact_version="CREATE",
                                    kfserving=True, transformer=TRANSFORMER_PATH, 
                                    topic_name=TOPIC_NAME, inference_logging="TRANSFORMED_AND_PREDICTIONS",
                                    instances=1, transformerInstances=1)
# List all available servings in the project
for s in serving.get_all():
    print(s.name)
# Get serving status
serving.get_status(SERVING_NAME)<jupyter_output><empty_output><jupyter_text>Start Model Serving Server<jupyter_code>if serving.get_status(SERVING_NAME) == 'Stopped':
    serving.start(SERVING_NAME)
import time
while serving.get_status(SERVING_NAME) != "Running":
    time.sleep(5) # Let the serving startup correctly
time.sleep(5)<jupyter_output><empty_output><jupyter_text>Sample credit card numbers<jupyter_code>import hsfs

connection = hsfs.connection()
fs = connection.get_feature_store()
td_meta = fs.get_training_dataset("card_fraud_model", 1)
#`init_prepared_statement` method is needed to get serving_keys in case `get_serving_vector` has not beed called yet. This is not necessary for `get_serving_vector` method itself
td_meta.init_prepared_statement() 
td_meta.serving_keys<jupyter_output><empty_output><jupyter_text>For demo purposes lets prepare list of primary key values that we are interested in to buils feature vectore from online feature store<jupyter_code>cc_nums = fs.get_feature_group("card_transactions", version=1).select("cc_num").read()
cc_nums_inputs = cc_nums.sample(n=len(cc_nums)*2, replace=True)
len(cc_nums_inputs)<jupyter_output><empty_output><jupyter_text>Get serving vector and send to Prediction Requests to the Served Model using Hopsworks REST API<jupyter_code>import numpy as np
TOPIC_NAME = serving.get_kafka_topic(SERVING_NAME)
print("Topic: " + TOPIC_NAME)
i=0
for cc_num in cc_nums_inputs['fg0.cc_num']:
    data = { "signature_name": "serving_default", "instances": [{'cc_num': int(cc_num)}] }
    response = serving.make_inference_request(SERVING_NAME, data)
    if i % 2000 == 0:
        print(response)
    i+=1<jupyter_output>{'predictions': [2.20478344]}
{'predictions': [0.955848038]}
{'predictions': [2.77835608]}
{'predictions': [1.0319711]}
{'predictions': [1.04669809]}
{'fraction_non_alphanumeric': 0.10880989180834622, 'fraction_numerical': 0.0241112828438949, 'mean_word_length': 6.143487858719647, 'pattern_counts': {'":': 3, '<': 23, '<?xml version=': 0, '>': 23, 'https://': 0, 'lorem ipsum': 0, 'www.': 0, 'xml': 0}, 'pii_count': 0, 'substrings_counts': 0, 'word_list_counts': {'cursed_substrings.json': 3, 'profanity_word_list.json': 0, 'sexual_word_list.json': 0, 'zh_pornsignals.json': 0}}
{'chain_length': '6', 'dir': 'jupyter-structured-clean-dedup', 'id': '578916', 'license': 'Apache-2.0', 'n_tokens_mistral': 1154, 'n_tokens_neox': 1072, 'n_words': 226, 'path': 'e2e_cc_fraud_detection/6_online_serving.ipynb', 'repo_name': 'javierdlrm/events', 'size': '3235'}