The SUSI iOS app provides responses for various queries but the response is always not accurate. To improve the response, we make use of the feedback system, which is the first step towards implementing Machine Learning on the SUSI Server. The way this works is that for every query, we present the user with an option to upvote or downvote the response and based on that a positive or negative feedback is saved on the server. In this blog, I will explain how this feedback system was implemented in the SUSI iOS app.
Steps to implement:
We start by adding the UI which is two buttons, one with a thumbs up and the other with a thumbs down image.
textBubbleView.addSubview(thumbUpIcon) textBubbleView.addSubview(thumbDownIcon) textBubbleView.addConstraintsWithFormat(format: "H:[v0]-4-[v1(14)]-2-[v2(14)]-8-|", views: timeLabel, thumbUpIcon, thumbDownIcon) textBubbleView.addConstraintsWithFormat(format: "V:[v0(14)]-2-|", views: thumbUpIcon) textBubbleView.addConstraintsWithFormat(format: "V:[v0(14)]-2-|", views: thumbDownIcon) thumbUpIcon.isUserInteractionEnabled = true thumbDownIcon.isUserInteractionEnabled = true
Here, we add the subviews and assign constraints so that these buttons align to the bottom right next to each other. Also, we enable the user interaction for these buttons.
We know that the user can rate the response by pressing either of the buttons added above. To do that we make an API call to the endpoint below:
BASE_URL+'/cms/rateSkill.json?'+'model='+model+'&group='+group+'&skill='+skill+’&language’+language+’&rating=’+rating
Here, the BASE_URL is the url of the server, the other three params model, group, language and skill are retrieved by parsing the skill location parameter we get with the response. The rating is positive or negative based on which button was pressed by the user. The skill param in the response looks like this:
skills:
[
"/susi_skill_data/models/general/entertainment/en/quotes.txt"
]
Let’s write the method that makes the API call and responds to the UI that it was successful.
if let accepted = response[ControllerConstants.accepted] as? Bool { if accepted { completion(true, nil) return } completion(false, ResponseMessages.ServerError) return }
Here after receiving a response from the server, we check if the `accepted` variable is true or not. Based on that, we pass `true` or `false` to the completion handler. Below the response we actually receive by making the request.
{ session: { identity: { type: "host", name: "23.105.140.146", anonymous: true } }, accepted: true, message: "Skill ratings updated" }
Finally, let’s update the UI after the request has been successful.
if sender == thumbUpIcon { thumbDownIcon.tintColor = UIColor(white: 0.1, alpha: 0.7) thumbUpIcon.isUserInteractionEnabled = false thumbDownIcon.isUserInteractionEnabled = true feedback = "positive" } else { thumbUpIcon.tintColor = UIColor(white: 0.1, alpha: 0.7) thumbDownIcon.isUserInteractionEnabled = false thumbUpIcon.isUserInteractionEnabled = true feedback = "negative" } sender.tintColor = UIColor.hexStringToUIColor(hex: "#2196F3")
Here, we check the sender (the thumbs up or down button) and based on that pass the rating (positive or negative) and update the color of the button.
Below is the app in action with the feedback system.
Resources:
- Tutorial on Raywanderlich discusses the way custom collection view cells are created
- Another tutorial on creating custom cells
- Alamofire Docs: explains usage of Alamofire to make API calls
- Material.io icons: source of the icons used