diff --git a/app/src/less/modules/smart-reply.less b/app/src/less/modules/smart-reply.less index c5c9c85..6cd536d 100644 --- a/app/src/less/modules/smart-reply.less +++ b/app/src/less/modules/smart-reply.less @@ -1,21 +1,27 @@ .smart-reply-container { clear: both; - padding-top: 15px; - height: 50px; - overflow: auto; - white-space: nowrap; + padding-top: 12px; + display: flex; + flex-wrap: wrap; + gap: 10px; } .smart-reply { - border: 3px solid @brand-primary; - padding: 10px 15px; - margin-right: 10px; - border-radius: 20px; + border: 2px solid @brand-primary; + padding: 9px 14px; + border-radius: 16px; background: @white; text-decoration: none !important; + color: @brand-primary; + box-shadow: 0 2px 6px fade(@brand-primary, 25%); + transition: all 120ms ease-in-out; } -.smart-reply:active { +.smart-reply:hover, +.smart-reply:active, +.smart-reply:focus { background: @brand-primary; color: @white; + box-shadow: 0 4px 10px fade(@brand-primary, 35%); + text-decoration: none; } \ No newline at end of file diff --git a/src/main/java/chatbot/lib/handlers/TextHandler.java b/src/main/java/chatbot/lib/handlers/TextHandler.java index 5638be6..e5f06f2 100644 --- a/src/main/java/chatbot/lib/handlers/TextHandler.java +++ b/src/main/java/chatbot/lib/handlers/TextHandler.java @@ -2,11 +2,14 @@ import chatbot.Application; import chatbot.lib.Utility; +import chatbot.lib.Constants; import chatbot.lib.handlers.dbpedia.LanguageHandler; import chatbot.lib.handlers.dbpedia.StatusCheckHandler; import chatbot.lib.request.Request; +import chatbot.lib.request.TemplateType; import chatbot.lib.response.ResponseData; import chatbot.lib.response.ResponseGenerator; +import chatbot.lib.response.ResponseType; import chatbot.rivescript.RiveScriptReplyType; import org.codehaus.jackson.JsonNode; import org.codehaus.jackson.map.ObjectMapper; @@ -25,6 +28,7 @@ public class TextHandler { private Request request; private String textMessage; private Application.Helper helper; + private boolean fallbackTriggered = false; private String sanitizeText(String message) { String result = message; @@ -74,6 +78,7 @@ public ResponseGenerator handleTextMessage() throws Exception { responseGenerator = new LocationHandler(request, rootNode.get("query").getTextValue(), helper).getLocation(); break; case RiveScriptReplyType.FALLBACK_SCENARIO: + fallbackTriggered = true; // Eliza if(textMessage.endsWith("!") || textMessage.endsWith(".")) { responseGenerator.addTextResponse(new ResponseData(helper.getEliza().processInput(textMessage))); @@ -90,6 +95,11 @@ public ResponseGenerator handleTextMessage() throws Exception { } } + // Add guided fallback suggestions when we could not understand + if(fallbackTriggered || responseGenerator.getResponse().size() == 0) { + responseGenerator = appendFallbackSuggestions(responseGenerator, textMessage); + } + // Fallback when everything else fails Eliza will answer if(responseGenerator.getResponse().size() == 0) { responseGenerator.addTextResponse(new ResponseData(helper.getEliza().processInput(textMessage))); @@ -97,6 +107,46 @@ public ResponseGenerator handleTextMessage() throws Exception { return responseGenerator; } + private ResponseGenerator appendFallbackSuggestions(ResponseGenerator responseGenerator, String originalText) { + // Base prompt text + String fallbackPrompt = helper.getRiveScriptBot().answer(request.getUserId(), RiveScriptReplyType.FALLBACK_TEXT)[0]; + responseGenerator.addTextResponse(new ResponseData(fallbackPrompt)); + + ResponseData smartReplies = new ResponseData(); + + // Fixed DBpedia-focused suggestions (no mixed/contextual items) + smartReplies.addSmartReply(new ResponseData.SmartReply("What is DBpedia?", TemplateType.DBPEDIA_ABOUT)); + smartReplies.addSmartReply(new ResponseData.SmartReply("How can I contribute?", TemplateType.DBPEDIA_CONTRIBUTE)); + smartReplies.addSmartReply(new ResponseData.SmartReply("Is DBpedia up?", TemplateType.CHECK_SERVICE + Utility.STRING_SEPARATOR + Constants.DBPEDIA_SERVICE)); + smartReplies.addSmartReply(new ResponseData.SmartReply("Show me DBpedia datasets", TemplateType.DBPEDIA_DATASET)); + smartReplies.addSmartReply(new ResponseData.SmartReply("How do I search with DBpedia Lookup?", TemplateType.DBPEDIA_LOOKUP)); + smartReplies.addSmartReply(new ResponseData.SmartReply("Tell me about DBpedia mappings", TemplateType.DBPEDIA_MAPPINGS)); + + responseGenerator.addSmartReplyResponse(smartReplies); + return responseGenerator; + } + + private String extractKeyword(String text) { + if(text == null || text.trim().length() == 0) { + return null; + } + String cleaned = text.replaceAll("[^A-Za-z0-9 ]", " ").toLowerCase(); + String[] tokens = cleaned.split(" +"); + String[] stop = new String[]{"what","who","where","why","how","is","are","the","a","an","of","in","on","for","with","to","tell","me","about","please"}; + java.util.Set stopSet = new java.util.HashSet<>(); + for(String s : stop) stopSet.add(s); + + String best = null; + for(String t : tokens) { + if(t.length() < 3) continue; + if(stopSet.contains(t)) continue; + if(best == null || t.length() > best.length()) { + best = t; + } + } + return best; + } + public String getTextMessage() { return textMessage; } diff --git a/src/main/resources/rivescript/scenario-text.rive b/src/main/resources/rivescript/scenario-text.rive index 756f4c4..fccbdba 100644 --- a/src/main/resources/rivescript/scenario-text.rive +++ b/src/main/resources/rivescript/scenario-text.rive @@ -41,7 +41,8 @@ - I'm sorry, DBpedia seems to be {uppercase}(@statusdown){/uppercase} right now. So I will be unable to answer factoid questions temporarily. + fallbacktext -- I'm sorry, but I couldn’t understand your question. I'm still learning, and will get better. + + - I couldn't understand that yet. Try one of these suggestions or rephrase with who/what/where. + noresultstext -- I'm sorry, I couldn’t find any results at this time. Please try again later. \ No newline at end of file + - I'm sorry, I couldn't find any results at this time. Please try again later. \ No newline at end of file