Motivation
"Artificial Intelligence (AI) is considered a major innovation that could disrupt many things. Some people even compare it to the Internet. A large investor firm predicted that some AI startups could become the next Apple, Google or Amazon within five years"- Prof. John Vu, Carnegie Mellon University.
Using chatbots to support our daily tasks is super useful and interesting. In fact, "Jenkins CI, Jira Cloud, and Bitbucket" have been becoming must-have apps in Slack of my team these days.
There are some existing approaches for chatbots including pattern matching, algorithms, and neutral networks. RiveScript is a scripting language using "pattern matching" as a simple and powerful approach for building up a Chabot.
Architecture
Actually, it was flexible to choose a programming language for the used Rivescript interpreter like Java, Go, Javascript, Python, and Perl. I went with Java.Used Technologies and Tools
- Oracle JDK 1.8.0_151
- Apache Maven 3.5.2
- Apache Tomcat 7.0.85
- RiveScript-Java
- Jersey sever/client
- MyFaces
Module ChatBot Backend
I had a backend for chatbot's brain which provided APIs responding to received messages from users via a GUI.1. Generate a web app project via Maven
mvn archetype:generate \ -DgroupId=vn.nvanhuong \ -DartifactId=chatbot_rivescript_backend \ -DarchetypeArtifactId=maven-archetype-webapp \ -DinteractiveMode=false;
Tips: When importing the project into Eclipse, I encountered an error "The superclass "javax.servlet.http.HttpServlet" was not found on the Java Build Path". I solved it by "Right click on the project/Properties/Project Facets/Runtimes/Check Apache Tomcat v.7.0"
2. Add dependencies needed in `pom.xml`
<project xmlns="http://maven.apache.org/POM/4.0.0" xmlns:xsi="http://www.w3.org/2001/XMLSchema-instance" xsi:schemaLocation="http://maven.apache.org/POM/4.0.0 http://maven.apache.org/maven-v4_0_0.xsd"> <modelVersion>4.0.0</modelVersion> <groupId>vn.nvanhuong</groupId> <artifactId>chatbot_rivescript_backend</artifactId> <packaging>war</packaging> <version>1.0-SNAPSHOT</version> <name>chatbot_rivescript_backend Maven Webapp</name> <url>http://maven.apache.org</url> <dependencies> <!-- ChatBot Brain --> <dependency> <groupId>com.rivescript</groupId> <artifactId>rivescript-core</artifactId> <version>0.10.0</version> </dependency> <!-- RESTful APIs --> <dependency> <groupId>com.sun.jersey</groupId> <artifactId>jersey-server</artifactId> <version>1.8</version> </dependency> <!-- JSON --> <dependency> <groupId>org.json</groupId> <artifactId>json</artifactId> <version>20160810</version> </dependency> <!-- Unit tests --> <dependency> <groupId>junit</groupId> <artifactId>junit</artifactId> <version>4.12</version> <scope>test</scope> </dependency> </dependencies> <build> <finalName>chatbot_rivescript_backend</finalName> </build> </project>
3. Create chatbot's brain with RiveScript
I created a file "chatbot_brain.rive" under the folder "src/main/resources/rivescript". I copied the content of template file "rs_standard.rive" at https://www.rivescript.com/try+ hello bot - Hello human!
4. Create RESTful APIs
package vn.nvanhuong.chatbot.rivescript.backend; import javax.ws.rs.POST; import javax.ws.rs.Path; import com.rivescript.Config; import com.rivescript.RiveScript; import com.sun.jersey.spi.resource.Singleton; @Path("/bot") @Singleton public class ChatBot { private RiveScript bot; public ChatBot() { String rivescriptFilePath = ChatBot.class.getClassLoader().getResource("rivescript").getFile(); bot = new RiveScript(Config.utf8()); bot.loadDirectory(rivescriptFilePath); bot.sortReplies(); } @POST public String getMsg(String msg) { return bot.reply("user", msg); } }
5. Configure RESTful at `web.xml`
<web-app id="WebApp_ID" version="2.4" xmlns="http://java.sun.com/xml/ns/j2ee" xmlns:xsi="http://www.w3.org/2001/XMLSchema-instance" xsi:schemaLocation="http://java.sun.com/xml/ns/j2ee http://java.sun.com/xml/ns/j2ee/web-app_2_4.xsd"> <display-name>Restful Web Application</display-name> <servlet> <servlet-name>jersey-serlvet</servlet-name> <servlet-class> com.sun.jersey.spi.container.servlet.ServletContainer </servlet-class> <init-param> <param-name>com.sun.jersey.config.property.packages</param-name> <param-value>vn.nvanhuong.chatbot.rivescript.backend</param-value> </init-param> <load-on-startup>1</load-on-startup> </servlet> <servlet-mapping> <servlet-name>jersey-serlvet</servlet-name> <url-pattern>/rest/*</url-pattern> </servlet-mapping> </web-app>
6. Write a test case
package vn.nvanhuong.chatbot.rivescript.backend.test; import static org.junit.Assert.assertEquals; import org.junit.Test; import vn.nvanhuong.chatbot.rivescript.backend.ChatBot; public class ChatBotTest { @Test public void should_say_hello() { ChatBot bot = new ChatBot(); assertEquals("Hello Human!", bot.getMsg("Hello Bot")); } }
7. Test the API with Postman
URL: http://localhost:8080/chatbot_rivescript_backend/rest/botModule ChatBot GUI
1. Generate a web app project via Maven
mvn archetype:generate \ -DgroupId=vn.nvanhuong \ -DartifactId=chatbot_rivescript_gui \ -DarchetypeArtifactId=maven-archetype-webapp \ -DinteractiveMode=false
2. Add dependencies needed in pom.xml
<project xmlns="http://maven.apache.org/POM/4.0.0" xmlns:xsi="http://www.w3.org/2001/XMLSchema-instance" xsi:schemaLocation="http://maven.apache.org/POM/4.0.0 http://maven.apache.org/maven-v4_0_0.xsd"> <modelVersion>4.0.0</modelVersion> <groupId>vn.nvanhuong</groupId> <artifactId>chatbot_rivescript_gui</artifactId> <packaging>war</packaging> <version>1.0-SNAPSHOT</version> <name>chatbot_rivescript_gui Maven Webapp</name> <url>http://maven.apache.org</url> <dependencies> <!-- JAX-RS Client --> <dependency> <groupId>org.glassfish.jersey.core</groupId> <artifactId>jersey-client</artifactId> <version>2.25.1</version> </dependency> <!-- JSF Pages --> <dependency> <groupId>org.apache.myfaces.core</groupId> <artifactId>myfaces-api</artifactId> <version>2.2.0</version> </dependency> <dependency> <groupId>org.apache.myfaces.core</groupId> <artifactId>myfaces-impl</artifactId> <version>2.2.0</version> </dependency> <!-- Unit test --> <dependency> <groupId>junit</groupId> <artifactId>junit</artifactId> <version>4.12</version> <scope>test</scope> </dependency> </dependencies> <build> <finalName>chatbot_rivescript_gui</finalName> </build> </project>
3. Configure JSF at web.xml
<?xml version="1.0" encoding="UTF-8"?> <web-app xmlns:xsi="http://www.w3.org/2001/XMLSchema-instance" xmlns="http://java.sun.com/xml/ns/javaee" xmlns:web="http://java.sun.com/xml/ns/javaee/web-app_2_5.xsd" xsi:schemaLocation="http://java.sun.com/xml/ns/javaee http://java.sun.com/xml/ns/javaee/web-app_2_5.xsd" version="2.5"> <!-- JSF mapping --> <servlet> <servlet-name>Faces Servlet</servlet-name> <servlet-class>javax.faces.webapp.FacesServlet</servlet-class> <load-on-startup>1</load-on-startup> </servlet> <servlet-mapping> <servlet-name>Faces Servlet</servlet-name> <url-pattern>*.xhtml</url-pattern> </servlet-mapping> <!-- welcome page --> <welcome-file-list> <welcome-file>index.xhtml</welcome-file> </welcome-file-list> </web-app>
4. Create a GUI
Rename index.jsp to index.xthml
<!DOCTYPE html> <html xmlns="http://www.w3.org/1999/xhtml" xmlns:f="http://java.sun.com/jsf/core" xmlns:h="http://java.sun.com/jsf/html" xmlns:p="http://xmlns.jcp.org/jsf/passthrough"> <h:head> <title>RiveScript</title> <style> .container { display: block; margin: 50px auto; width: 90%; } .chatbox { height: 600px; border: solid 1px #039; background-image: url(bot_logo.png); background-repeat: no-repeat; background-position: center; background-size: contain; display: flex; justify-content: center; align-items: center; } .chatbox .bot-dialog { width: 90%; border: dashed 1px purple; text-align: center; background-color: orange; } .chatbox .bot-dialog > span{ font-size: larger; } .message { display: flex; justify-content: space-between; } .message > input.message-input { width: 90%; margin-top: 10px; line-height: 2.3; } .message > input.submit { width: 9%; background-color: #039; color: white; font-size: 15px; margin-top: 10px; } .message-display > span { font-style: italic; } .message-display > label { font-weight: bold; } .message-display { margin-top: 5px; } </style> </h:head> <h:body> <h:form> <h:panelGroup layout="block" styleClass="container"> <h:panelGroup layout="block" styleClass="chatbox"> <h:panelGroup layout="block" styleClass="bot-dialog"> <h:outputText id="botMessage" value="#{controller.botMessage}" escape="false"/> </h:panelGroup> </h:panelGroup> <h:panelGroup layout="block" styleClass="message"> <h:inputText id="input" value="#{controller.humanMessage}" styleClass="message-input" p:placeholder="Send a message to the bot" p:autofocus="true" onblur="this.focus()"/> <h:commandButton id="button" value="Send" actionListener="#{controller.onSend}" styleClass="submit"/> </h:panelGroup> <h:panelGroup layout="block" styleClass="message-display" rendered="#{not empty controller.humanMessageDisplay}"> <h:outputLabel for="messageDisplay" value="You just said: "/> <h:outputText id="messageDisplay" value="#{controller.humanMessageDisplay}"/> </h:panelGroup> </h:panelGroup> </h:form> </h:body> </html>
5. Create a Controller to call the RESTful APIs
package vn.vanhuong.chatbot.rivescript.gui; import javax.faces.bean.ManagedBean; import javax.faces.event.ActionEvent; import javax.ws.rs.client.ClientBuilder; import javax.ws.rs.client.Entity; import javax.ws.rs.core.MediaType; import javax.ws.rs.core.Response; @ManagedBean(name = "controller") public class Controller { private String humanMessage; private String botMessage; private String humanMessageDisplay; public void onSend(ActionEvent event) { Response response = ClientBuilder.newClient().target("http://localhost:8080/chatbot_rivescript_backend/rest/bot") .request(MediaType.APPLICATION_FORM_URLENCODED) .post(Entity.entity(humanMessage, MediaType.APPLICATION_FORM_URLENCODED)); this.botMessage = response.readEntity(String.class); this.humanMessageDisplay = humanMessage; this.humanMessage = null; } public String getHumanMessage() { return humanMessage; } public void setHumanMessage(String humanMessage) { this.humanMessage = humanMessage; } public String getBotMessage() { return botMessage; } public void setBotMessage(String botMessage) { this.botMessage = botMessage; } public String getHumanMessageDisplay() { return humanMessageDisplay; } public void setHumanMessageDisplay(String humanMessageDisplay) { this.humanMessageDisplay = humanMessageDisplay; } }
6. Enjoy playing with your ChatBot
Check out my source code as below
- Backend: https://github.com/vnnvanhuong/chatbot_rivescript_backend.git- GUI: https://github.com/vnnvanhuong/chatbot_rivescript_gui.git
References:
[1]. http://science-technology.vn/?p=5761
[2]. https://www.rivescript.com/interpreters
[3]. https://github.com/aichaos/rivescript-java
[4]. https://youtu.be/wf8w1BJb9Xc
Comments
Post a Comment