In this blog series we’ll have a look at an example I built in Python that uses Azure Cognitive Services and Azure Storage.
First of all what is Azure Cognitive Services? In Microsoft’s own words is a set of API calls to embed the ability to see, hear, speak, search, understand and accelerate decision-making into your apps. Technically Personaliser does sit under the Azure Cognitive Services umbrella but Microsoft is trying to market this as a stand alone service, it is defined as an API services that offers the ability to prioritise content, layouts and conversations through reinforcement learning. In other words is a recommendation system, like when on YouTube you watch a video and then similar ones are recommended.
This simple python application is structured like this
There are three python files each with a diffrent function:
- AZStorageConnector.py takes care of handling any request to Blob Storage, from reading files (in our case images) to inserting rows in a CosmosDB table
- ImageReader reads all images saved in the file share and pass them on to the Compuer Vision API which returns a brief description of the image that is then saved on a CosmosDB table
- Personaliser.py supplies the image descriptions to the Personaliser API which returns the name of an image which it thinks is most likely to interest the user
Azure (Cognitive Services) Personaliser.
Needless to say you need to have an Azure account and subscription or you must create one for free with a trial included.
Once that’s done click here and create the resource, you need to specify:
- Name of the resource (this can be anything you want)
- Subscription you want to use (or pay as you go)
- Location
- Pricing tier
- Resource group (It’s handy to have all resources used in this demo under the same group)
Next go to the Azure portal and access the Personaliser resrouce, from there you need the following
- Endpoint (from the overview)
- One of the the two keys
Before we start coding we need to create two environment variables in windows, one called PERSONALISER_KEY and another PERSONALISER_ENDPOINT which will contain, respectively, the key and the endpoint we just retrieved.
from azure.cognitiveservices.personalizer import PersonalizerClient from azure.cognitiveservices.personalizer.models import RankableAction, RewardRequest, RankRequest from msrest.authentication import CognitiveServicesCredentials from AZStorageConnector import AZStorageConnector import ast import datetime, json, os, time, uuid try: key_var_name = 'PERSONALISER_KEY' aZStorageConnection = AZStorageConnector() blobList = aZStorageConnection.blobReader() if not key_var_name in os.environ: print raise Exception('Please set/export the environment variable: {}'.format(key_var_name)) personalizer_key = os.environ[key_var_name] # Replace <your-resource-name>: https://<your-resource-name>.api.cognitive.microsoft.com/ endpoint_var_name = 'PERSONALISER_ENDPOINT' if not endpoint_var_name in os.environ: raise Exception('Please set/export the environment variable: {}'.format(endpoint_var_name)) personalizer_endpoint = os.environ[endpoint_var_name] except Exception as e: print("exception message:"+ str(e)) input("Press Enter to continue...") # Instantiate a Personalizer client client = PersonalizerClient(personalizer_endpoint, CognitiveServicesCredentials(personalizer_key)) def get_actions(): actions = [] row = aZStorageConnection.tableReader() for r in row: actions.append(RankableAction(id= r.imgDesc, features=[ast.literal_eval(r.tags)])) # action4 = RankableAction(id='salad', features=[{'taste':'salty', 'spice_level':'none'},{'nutritional_level': 2}]) return actions def get_user_preference(): res = {} features = [] row = aZStorageConnection.tableReader() for r in row: tags = ast.literal_eval(r.tags) for value,key in tags.items(): features.append(key) features = list(dict.fromkeys(features)) for i in range(len(features)): print(str(i+1) +" - "+features[i]) pref = input("What image feature would you prefer? Enter number\n") try: ppref = int(pref) if(ppref<=0 or ppref>len(features)): raise IndexError res['taste_preference'] = features[ppref-1] except (ValueError, IndexError): print("Entered value is invalid. Setting feature value to", features[0]+ ".") res['taste_preference'] = features[0] return res # create the learning loop keep_going = True while keep_going: eventid = str(uuid.uuid4()) context = [get_user_preference()] actions = get_actions() try: rank_request = RankRequest( actions=actions, context_features=context, event_id=eventid) response = client.rank(rank_request=rank_request) except Exception as e: print("exception message:"+ str(e)) input("Press Enter to continue...") print("Personalizer service ranked the actions with the probabilities listed below:") rankedList = response.ranking for ranked in rankedList: print(ranked.id, ':',ranked.probability) print("Personalizer thinks you would like to have", response.reward_action_id+".") answer = input("Is this correct?(y/n)\n")[0] reward_val = "0.0" if(answer.lower()=='y'): reward_val = "1.0" elif(answer.lower()=='n'): reward_val = "0.0" else: print("Entered choice is invalid. Service assumes that you didn't like the recommended food choice.") client.events.reward(event_id=eventid, value=reward_val) br = input("Press Q to exit, any other key to continue: ") if(br.lower()=='q'): keep_going = False #request a rank rank_request = RankRequest( actions=actions, context_features=context, excluded_actions=['juice'], event_id=eventid) response = client.rank(rank_request=rank_request) print("response="+response) input("Press Enter to continue...3") #send a reward reward_val = "0.0" if(answer.lower()=='y'): reward_val = "1.0" elif(answer.lower()=='n'): reward_val = "0.0" else: print("Entered choice is invalid. Service assumes that you didn't like the recommended food choice.") client.events.reward(event_id=eventid, value=reward_val)