Applying Private Skill as Web Bots in SUSI Chat

Along with public skills, we now have private skills as web bots! Users can create their own private skills which can be used only by them and in the chatbots deployed by them. The SUSI Server accepts parameters to identify a valid private skill and applies that private skill for a particular chat. It then executes the query and sends the response to the client. This blog explains how private skill is applied in the SUSI Chat.

Understanding the API

The API to receive response from SUSI is /susi/chat.json. For applying only the public skills, we can send a request like /susi/chat.json?q=hello. Here only one parameter “q” is involved in which we send the query. However, for a private skill, the following parameters are involved:

  • privateskill – when the client sends this parameter, it indicates to use a private skill.
  • userid – the userid of the user who has created the private skill
  • group – the group name of the private skill
  • language – the language of the private skill
  • skill – the skill name of the private skill

Thus, the four parameters userid, group, language, skill serves to uniquely identify a private skill.

Fetching the private skill

After the client sends the appropriate parameters to apply a private skill, the server must actually apply the private skill. This is done in a similar manner how persona and dream skills are applied. The First step is the fetch the private skill from the susi_private_skill_data folder.

// read the private skill
File private_skill_dir = new File(DAO.private_skill_watch_dir,userId);
File group_file = new File(private_skill_dir, group_name);
File language_file = new File(group_file, language);
skillfile = SusiSkill.getSkillFileInLanguage(language_file, skill_name, false);
String text = new String(Files.readAllBytes(skillfile.toPath()), StandardCharsets.UTF_8);

Applying the private skill

After we have fetched the private skill, the next step is to apply it. To do this, we create a SusiMind object and add it to the general minds variable. Thus the skill will be applied to the particular chat with the highest priority, since it will be the first skill to be added to the minds variable. Later, the public skills can be added to the minds variable, thus their priority will be lower than the private skill.

String text = new String(Files.readAllBytes(skillfile.toPath()), StandardCharsets.UTF_8);
// fill an empty mind with the private skill
SusiMind awakeMind = new SusiMind(DAO.susi_chatlog_dir, DAO.susi_skilllog_dir); // we need the memory directory here to get a share on the memory of previous dialoges, otherwise we cannot test call-back questions
JSONObject rules = SusiSkill.readLoTSkill(new BufferedReader(new InputStreamReader(new ByteArrayInputStream(text.getBytes(StandardCharsets.UTF_8)), StandardCharsets.UTF_8)), SusiLanguage.unknown, dream);
awakeMind.learn(rules, skillfile);
SusiSkill.ID skillid = new SusiSkill.ID(skillfile);
SusiSkill activeskill = awakeMind.getSkillMetadata().get(skillid);
awakeMind.setActiveSkill(activeskill);
// we are awake!
minds.add(awakeMind);

 

Result

Example API: http://localhost:4000/susi/chat.json?q=hi&privateskill=1&userid=17a70987d09c33e6f56fe05dca6e3d27&group=Knowledge&language=en&skill=knowprides

The skill exists in the correct location:

The skill file content is:

Thus, on sending the query “tell me” with the other parameters, we get the correct reply i.e “yes sure” from the server:

Resources

 

 

Continue Reading

Making API for Fetching Private Skill Bot Settings from Server

SUSI Server needs to provide an API which would return the private skill’s metadata. This metadata will include the chatbot’s design and configuration settings. The skill’s meta data is being stored in the chatbot.json file in the server. This API will be called from the websites where the chatbot has been deployed. The skill’s metadata will be used for customizing the design of the chatbot. This blog explains how the API for fetching a private skill bot’s metadata is made.

Understanding the API

The API used to fetch public skill’s metadata is /cms/getSkillMetadata.json, with the following parameters:

  • Model
  • Group
  • Language
  • Skill

These parameters help to uniquely identify the skill.

The same API is used to fetch private skill’s metadata too. But the parameters changes to:

  • userid
  • Group
  • Language
  • Skill

The userid also helps to secure the identity of the user. Unlike email id, the user can be easily identified using the userid. Also it prevents from accessing other user’s chatbots without knowing their userid.

Understanding the data stored

In the chatbot.json file, the skill’s metadata are stored in the following format:

{"17a70987d09c33e6f56fe05dca6e3d27": {"Knowledge": {"en": {"test2new1": {
  "design": {
    "botIconColor": "#000000",
    "userMessageTextColor": "#ffffff",
    "botMessageBoxBackground": "#f8f8f8",
    "userMessageBoxBackground": "#0077e5",
    "botMessageTextColor": "#455a64",
    "bodyBackground": "#ffffff"
  },
  "configure": {
    "sites_enabled": "website1.com, website2.com",
    "sites_disabled": "website3.com"
  },
  "timestamp": "2018-07-20 01:04:39.571"
}}}}}

 

Thus, each entry is stored as a key-value pair. This makes the retrieval of record very efficient.

Making API to fetch private skill bot’s settings

In GetSkillMetadataService.java file, we detect if the client is sending the “userid” parameter or not. For fetching public skill’s metadata, the client will send the “model” parameter and for fetching private skill bot’ settings, the client will send the “userid” parameter. To fetch the private skill bot’s settings, we need to extract it from the chatbot.json file. We fetch the entire object for the particular skill and return it:

// fetch private skill (chatbot) meta data
JsonTray chatbot = DAO.chatbot;
JSONObject json = new JSONObject(true);
JSONObject userObject = chatbot.getJSONObject(userid);
JSONObject groupObject = userObject.getJSONObject(group);
JSONObject languageObject = groupObject.getJSONObject(language);
JSONObject skillObject = languageObject.getJSONObject(skillname);
json.put("skill_metadata", skillObject);
json.put("accepted", true);
json.put("message", "Success: Fetched Skill's Metadata");
return new ServiceResponse(json);

 

Result

Example API request: http://127.0.0.1:4000/cms/getSkillMetadata.json?userid=17a70987d09c33e6f56fe05dca6e3d27&group=Knowledge&language=en&skill=testnew

This gives the following output:

{
  "skill_metadata": {
    "design": {
      "botIconColor": "#000000",
      "userMessageTextColor": "#ffffff",
      "botMessageBoxBackground": "#f8f8f8",
      "userMessageBoxBackground": "#0077e5",
      "botMessageTextColor": "#455a64",
      "bodyBackground": "#ffffff"
    },
    "configure": {
      "sites_enabled": "website1.com, website2.com",
      "sites_disabled": "website3.com"
    },
    "timestamp": "2018-07-20 01:39:55.205"
  },
  "accepted": true,
  "message": "Success: Fetched Skill's Metadata",
  "session": {"identity": {
    "type": "host",
    "name": "127.0.0.1_af2c1fe3",
    "anonymous": true
  }}
}

 

Resources

Continue Reading

Fetching Private Skill from SUSI Server

SUSI Server needs to provide an API which would return the private skill’s file content. The private skill is used for the botbuilder project. Since the skill is private, the fetching process is little different from that of the public skills. The client has to provide the user’s access_token and a parameter private to access the private skill instead of the public skill. This blog explains how the private skill is being fetched from the SUSI Server.

Understanding the API

The API used to fetch public skill is /cms/getSkill.json, with the following parameters:

  • Model
  • Group
  • Language
  • Skill

These parameters helps to uniquely identify the skill.

The same API is used to fetch private skill too. But the parameters changes to:

  • Access_token
  • Private
  • Group
  • Language
  • Skill

The access token is used to authenticate the user, since the user should only be able to fetch their own private skill. The access token is also used to extract the user’s UUID which will be useful for locating the private skill.

String userId = null;
if (call.get("access_token") != null) { // access tokens can be used by api calls, somehow the stateless equivalent of sessions for browsers
ClientCredential credential = new ClientCredential(ClientCredential.Type.access_token, call.get("access_token"));
Authentication authentication = DAO.getAuthentication(credential);
// check if access_token is valid
if (authentication.getIdentity() != null) {
ClientIdentity identity = authentication.getIdentity();
userId = identity.getUuid();
}
}

 

Fetching the Private Skill from private skill repository

Now that we have all the necessary parameters, we can fetch the private skill from the susi_private_skill_data repository. The susi_private_skill_data folder has the following structure:

Thus to locate the skill, we will need the above parameters which we got from client and the user’s UUID. The following code checks if the client is requesting for private skill and changes the directory path accordingly.

// if client sends private=1 then it is a private skill
String privateSkill = call.get("private", null);
File private_skill_dir = null;
if(privateSkill != null){
private_skill_dir = new File(DAO.private_skill_watch_dir,userId);
}
String model_name = call.get("model", "general");
File model = new File(DAO.model_watch_dir, model_name);
if(privateSkill != null){
model = private_skill_dir;
}

 

Result:

Resources

Continue Reading

Store User’s Chatbots in SUSI Server

Users can create their own private skill which corresponds to their susi bot in SUSI Server. We store these private skills inside the susi_private_skill_data directory. We also store the information of the chatbots of each user in chatbot.json file inside the local storage of the server. It contains the list of chatbots created by each user against their UUIDs. This makes it easier and more organised to retrieve the chatbots of the users and their associated settings. This blog explains how the chatbots are being saved in the chatbot.json file in the SUSI server.

Receiving Private Skill from client

The client can create a private skill by accessing the /cms/createSkill.txt API. Along with the other parameters used to create a skill, it also has to send private=1 so that the server can recognise that this is a private skill. The private skills are stored in the folder susi_private_skill_data. The API is made by the CreateSkillService.java file.

protected void doPost(HttpServletRequest req, HttpServletResponse resp) throws ServletException, IOException {
    resp.setHeader("Access-Control-Allow-Origin", "*"); // enable CORS
    String userEmail = null;
    JSONObject json = new JSONObject();
    Part imagePart = req.getPart("image");
    if (req.getParameter("access_token") != null) {
        if (imagePart == null) {
            json.put("accepted", false);
            json.put("message", "Image not given");
        } 

 

Getting skill parameters and Saving skill locally

The client sends various parameters related to the skill. Such as the group name, language, skill name, image, etc. Also to identify the skill as a private skill, it needs to send private=1 parameter. If it is a private skill, then we call the function storePrivateSkillBot().

if(privateSkill != null){
    this.storePrivateSkillBot(userId, skill_name, group_name, language_name);
    try (Git git = DAO.getPrivateGit()) {
        git.add().addFilepattern(".").call();
        // commit the changes
        DAO.pushCommit(git, "Created " + skill_name, userEmail);
        json.put("accepted", true);

    } catch (IOException | GitAPIException e) {
        e.printStackTrace();
        json.put("message", "error: " + e.getMessage());

    }
}

 

Creating the chatbot.json file and saving user’s bot

Inside the function storePrivateSkillBot(), we create the json file in the local storage and save the user’s bot along with their user ids. If the bot with the same name already exists, then we update it or else create a new one.

private static void storePrivateSkillBot(String userId, String skillName, String group, String language) {
    JsonTray chatbot = DAO.chatbot;
    JSONArray userBots = new JSONArray();
    JSONObject botObject = new JSONObject();
    JSONObject userChatBotsObject = new JSONObject();
    if (chatbot.has(userId)) {
        userBots = chatbot.getJSONObject(userId).getJSONArray("chatbots");
    }
        // save a new bot
    botObject.put("name",skillName);
    botObject.put("group",group);
    botObject.put("language",language);
    userBots.put(botObject);
    userChatBotsObject.put("chatbots",userBots);
    chatbot.put(userId,userChatBotsObject,true);
} 

 

In chatbot.json file, on creating private skills, the following json gets stored:

Resources

 

Continue Reading
Close Menu