Πώς να δημιουργήσετε ένα Chatbot με το React

Η φιλοσοφία μου είναι απλή. Για να γίνεις καλός σε κάτι, πρέπει να το κάνεις πολύ.

Δεν είναι αρκετό να το κάνεις μία φορά. Πρέπει να το κάνετε ξανά και ξανά και ξανά. Δεν θα τελειώσει ποτέ. Χρησιμοποίησα την ίδια φιλοσοφία για να γίνω καλός στον προγραμματισμό.

Ένα πράγμα που έχω παρατηρήσει σε αυτό το ταξίδι είναι ότι είναι πολύ πιο διασκεδαστικό να κατασκευάζεις πράγματα που είναι ενδιαφέροντα και που φαίνονται καλά. Πράγματα για τα οποία μπορείτε να δείξετε φίλους και να είστε περήφανοι. Κάτι που σας ενθουσιάζει να ξεκινήσετε όταν κάθεστε μπροστά από το πληκτρολόγιό σας.

Γι 'αυτό δημιούργησα ένα chatbot.

Που μεταμορφώθηκε σε ένα πακέτο npm.

Ας φτιάξουμε λοιπόν μαζί. Εάν θέλετε να αντιμετωπίσετε μόνοι σας αυτήν την πρόκληση, μπορείτε να μεταβείτε απευθείας στην τεκμηρίωση (που είναι στην πραγματικότητα ένα chatbot). Ή, εάν είστε οπτικός μαθητής, θα δημιουργήσω ένα σεμινάριο στο YouTube.

Διαφορετικά, ας πάμε. Θα υποθέσω ότι έχετε εγκαταστήσει τον κόμβο και πρόσβαση στην εντολή npx. Εάν όχι, πάρε το εδώ.

Αρχική εγκατάσταση

// Run these commands from your command line npx create-react-app chatbot cd chatbot yarn add react-chatbot-kit yarn start

Αυτό θα πρέπει να εγκαταστήσει το πακέτο npm και να ανοίξει το διακομιστή ανάπτυξης στο localhost: 3000.

Στη συνέχεια, προχωρήστε App.jsκαι πραγματοποιήστε αυτές τις αλλαγές:

import Chatbot from 'react-chatbot-kit' function App() { return ( ); }

Καλή δουλειά. Φτάνουμε εκεί. Θα πρέπει να το δείτε αυτό στον διακομιστή ανάπτυξης τώρα:

Το chatbot παίρνει τρία στηρίγματα που πρέπει να συμπεριληφθούν για να λειτουργήσει. Πρώτον, χρειάζεται μια διαμόρφωση που πρέπει να περιλαμβάνει μια initialMessagesιδιότητα με αντικείμενα μηνυμάτων chatbot.

Δεύτερον, χρειάζεται μια MessageParserκλάση που πρέπει να εφαρμόσει μια μέθοδο ανάλυσης.

Τρίτον, χρειάζεται μια ActionProviderτάξη που θα εφαρμόζει ενέργειες που θέλουμε να κάνουμε με βάση την ανάλυση του μηνύματος.

Θα το κάνουμε πιο βαθιά αργότερα. Προς το παρόν, μεταβείτε εδώ για να λάβετε τον κωδικό boilerplate για να ξεκινήσετε.

  • Βάλτε τον MessageParserκωδικό σε ένα αρχείο που ονομάζεταιMessageParser.js
  • Βάλτε τον ActionProviderκωδικό σε ένα αρχείο που ονομάζεταιActionProvider.js
  • Τοποθετήστε τον κωδικό διαμόρφωσης σε ένα αρχείο που ονομάζεται config.js

Όταν τελειώσετε, επιστρέψτε στο App.jsαρχείο σας και προσθέστε αυτόν τον κωδικό:

import React from 'react'; import Chatbot from 'react-chatbot-kit' import './App.css'; import ActionProvider from './ActionProvider'; import MessageParser from './MessageParser'; import config from './config'; function App() { return ( ); }

Θα πρέπει να το δείτε τώρα στο localhost: 3000:

Γλυκός. Τώρα έχουμε το chatbot που αποδίδεται στην οθόνη και μπορούμε να γράψουμε στο πεδίο εισαγωγής και να το υποβάλουμε για να στείλουμε ένα μήνυμα στη συνομιλία. Αλλά όταν το δοκιμάζουμε αυτό, δεν συμβαίνει τίποτα.

Κατανόηση του τρόπου λειτουργίας του chatbot

Εδώ πρέπει να κάνουμε μια στάση pit και να ρίξουμε μια ματιά στο πώς MessageParserκαι το ActionProviderαλληλεπιδρά για να κάνει το bot μας να δράσει.

Όταν το bot αρχικοποιηθεί, η initialMessagesιδιότητα από το config τοποθετείται στην εσωτερική κατάσταση του chatbot σε μια ιδιότητα που ονομάζεται messages, η οποία χρησιμοποιείται για την απόδοση μηνυμάτων στην οθόνη.

Επιπλέον, όταν γράφουμε και πατάμε το κουμπί υποβολής στο πεδίο συνομιλίας, το MessageParser(το οποίο περάσαμε ως στηρίγματα στο chatbot) καλεί τη parseμέθοδο του. Γι 'αυτό πρέπει να εφαρμοστεί αυτή η μέθοδος.

Ας ρίξουμε μια πιο προσεκτική ματιά στον MessageParserκωδικό εκκίνησης:

class MessageParser { constructor(actionProvider) { this.actionProvider = actionProvider; } parse(message) { ... parse logic } }

Αν κοιτάξουμε προσεκτικά, αυτή η μέθοδος κατασκευάζεται με ένα actionProvider. Αυτή είναι η ίδια ActionProviderτάξη που περνάμε ως στηρίγματα στο chatbot. Αυτό σημαίνει ότι ελέγχουμε δύο πράγματα - τον τρόπο ανάλυσης του μηνύματος και την ενέργεια που πρέπει να αναλάβουμε βάσει της εν λόγω ανάλυσης.

Ας χρησιμοποιήσουμε αυτές τις πληροφορίες για να δημιουργήσουμε μια απλή απάντηση στο chatbot. Πρώτα αλλάξτε το MessageParserεξής:

class MessageParser { constructor(actionProvider) { this.actionProvider = actionProvider; } parse(message) { const lowerCaseMessage = message.toLowerCase() if (lowerCaseMessage.includes("hello")) { this.actionProvider.greet() } } } export default MessageParser

Τώρα MessageParserλαμβάνουμε το μήνυμα χρήστη, ελέγχοντας αν περιλαμβάνει τη λέξη "γεια". Εάν ναι, καλεί τη greetμέθοδο στο actionProvider.

Αυτήν τη στιγμή, αυτό θα συντριβεί, επειδή δεν έχουμε εφαρμόσει τη greetμέθοδο. Ας το κάνουμε στη συνέχεια. Προχωρήστε σε ActionProvider.js:

class ActionProvider { constructor(createChatBotMessage, setStateFunc) { this.createChatBotMessage = createChatBotMessage; this.setState = setStateFunc; } greet() { const greetingMessage = this.createChatBotMessage("Hi, friend.") this.updateChatbotState(greetingMessage) } updateChatbotState(message) { // NOTE: This function is set in the constructor, and is passed in // from the top level Chatbot component. The setState function here // actually manipulates the top level state of the Chatbot, so it's // important that we make sure that we preserve the previous state. this.setState(prevState => ({ ...prevState, messages: [...prevState.messages, message] })) } } export default ActionProvider

Ομορφη. Τώρα αν πληκτρολογήσουμε "γεια" στο πεδίο συνομιλίας, θα το λάβουμε ξανά:

Φανταστικός. Τώρα που μπορούμε να ελέγξουμε την ανάλυση του μηνύματος και να απαντήσουμε με μια ενέργεια, ας προσπαθήσουμε να κάνουμε κάτι πιο περίπλοκο. Ας προσπαθήσουμε να φτιάξουμε ένα bot που σας παρέχει μαθησιακούς πόρους για τη γλώσσα προγραμματισμού που ζητάτε.

Δημιουργία εκμάθησης

Αρχικά, ας επιστρέψουμε στο config.jsαρχείο μας και κάνουμε μερικές μικρές αλλαγές:

import { createChatBotMessage } from 'react-chatbot-kit'; const config = { botName: "LearningBot", initialMessages: [createChatBotMessage("Hi, I'm here to help. What do you want to learn?")], customStyles: { botMessageBox: { backgroundColor: "#376B7E", }, chatButton: { backgroundColor: "#376B7E", }, }, } export default config

Εντάξει, οπότε προσθέσαμε μερικές ιδιότητες εδώ και αλλάξαμε το αρχικό μας μήνυμα. Ειδικότερα, δώσαμε στο bot ένα όνομα και αλλάξαμε το χρώμα των στοιχείων messageboxκαι των chatbuttonστοιχείων.

Καλώς. Τώρα φτάνουμε στο καλό.

Όχι μόνο μπορούμε να αναλύσουμε τα μηνύματα και να απαντήσουμε στον χρήστη με ένα μήνυμα chatbot, αλλά μπορούμε να ορίσουμε προσαρμοσμένα στοιχεία React που θέλουμε να αποδώσουμε με το μήνυμα. Αυτά τα στοιχεία μπορούν να είναι οτιδήποτε θέλουμε - είναι απλά απλά παλιά στοιχεία του React.

Ας το δοκιμάσουμε δημιουργώντας ένα στοιχείο επιλογών που θα καθοδηγήσει τον χρήστη σε πιθανές επιλογές.

Κατ 'αρχάς, ορίζουμε το στοιχείο επιλογών μάθησης:

// in src/components/LearningOptions/LearningOptions.jsx import React from "react"; import "./LearningOptions.css"; const LearningOptions = (props) => { const options = [ { text: "Javascript", handler: () => {}, id: 1 }, { text: "Data visualization", handler: () => {}, id: 2 }, { text: "APIs", handler: () => {}, id: 3 }, { text: "Security", handler: () => {}, id: 4 }, { text: "Interview prep", handler: () => {}, id: 5 }, ]; const optionsMarkup = options.map((option) => (  {option.text}  )); return {optionsMarkup} ; }; export default LearningOptions; // in src/components/LearningOptions/LearningOptions.css .learning-options-container { display: flex; align-items: flex-start; flex-wrap: wrap; } .learning-option-button { padding: 0.5rem; border-radius: 25px; background: transparent; border: 1px solid green; margin: 3px; }

Now that we have our component, we need to register it with our chatbot. Head over to config.js and add the following:

import React from "react"; import { createChatBotMessage } from "react-chatbot-kit"; import LearningOptions from "./components/LearningOptions/LearningOptions"; const config = { initialMessages: [ createChatBotMessage("Hi, I'm here to help. What do you want to learn?", { widget: "learningOptions", }), ], ..., widgets: [ { widgetName: "learningOptions", widgetFunc: (props) => , }, ], }

Understanding widgets

Alright. Let's take a breather and explore what we've done.

  1. We created the LearningOptions component.
  2. We registered the component under widgets in our config.
  3. We gave the createChatbotMessage function an options object specifying which widget to render with this message.

The result:

Fantastic, but why did we need to register our component in the config as a widget function?

By giving it a function, we control when we perform the invocation. This allows us room to decorate the widget with important properties inside the chatbot.

The widget that we define will receive a number of properties from the chatbot (some of which can be controlled by config properties):

  1. actionProvider - we give the actionProvider to the widget in order to execute actions if we need to.
  2. setState - we give the top level chatbot setState function to the widget in case we need to manipulate state.
  3. scrollIntoView - utility function to scroll to the bottom of the chat window, should we need to adjust the view.
  4. props - if we define any props in the widget config, those will be passed to the widget under the property name configProps.
  5. state - if we define custom state in the config, we can map it to the widget by using the mapStateToProps property

If you recall, we defined some options in the LearningOptions component:

 const options = [ { text: "Javascript", handler: () => {}, id: 1 }, { text: "Data visualization", handler: () => {}, id: 2 }, { text: "APIs", handler: () => {}, id: 3 }, { text: "Security", handler: () => {}, id: 4 }, { text: "Interview prep", handler: () => {}, id: 5 }, ];

Currently these have an empty handler. What we want to do now is to replace this handler by a call to the actionProvider.

So what do we want to have happen when we execute these functions? Ideally, we'd have some sort of chatbot message, and an accompanying widget that displays a list of links to helpful resources for each topic. So let's see how we can implement that.

First, we need to create the link list component:

// in src/components/LinkList/LinkList.jsx import React from "react"; import "./LinkList.css"; const LinkList = (props) => { const linkMarkup = props.options.map((link) => ( 
  • {link.text}
  • )); return
      {linkMarkup}
    ; }; export default LinkList; // in src/components/LinkList/LinkList.css .link-list { padding: 0; } .link-list-item { text-align: left; font-size: 0.9rem; } .link-list-item-url { text-decoration: none; margin: 6px; display: block; color: #1d1d1d; background-color: #f1f1f1; padding: 8px; border-radius: 3px; box-shadow: 2px 2px 4px rgba(150, 149, 149, 0.4); }

    Great. We now have a component that can display a list of links. Now we need to register it in in the widget section of the config:

    import React from "react"; import { createChatBotMessage } from "react-chatbot-kit"; import LearningOptions from "./components/LearningOptions/LearningOptions"; import LinkList from "./components/LinkList/LinkList"; const config = { ... widgets: [ { widgetName: "learningOptions", widgetFunc: (props) => , }, { widgetName: "javascriptLinks", widgetFunc: (props) => , }, ], }; export default config; 

    So far so good, but we want to dynamically pass in props to this component so that we can reuse it for the other options as well. This means that we need to add another property to the widget object in the config:

    import React from "react"; import { createChatBotMessage } from "react-chatbot-kit"; import LearningOptions from "./components/LearningOptions/LearningOptions"; import LinkList from "./components/LinkList/LinkList"; const config = { ..., widgets: [ ..., { widgetName: "javascriptLinks", widgetFunc: (props) => , props: { options: [ { text: "Introduction to JS", url: "//www.freecodecamp.org/learn/javascript-algorithms-and-data-structures/basic-javascript/", id: 1, }, { text: "Mozilla JS Guide", url: "//developer.mozilla.org/en-US/docs/Web/JavaScript/Guide", id: 2, }, { text: "Frontend Masters", url: "//frontendmasters.com", id: 3, }, ], }, }, ], }; export default config; 

    Now these props will be passed to the LinkList component as props.

    Now we need to do two more things.

    1. We need to add a method to the actionProvider
    class ActionProvider { constructor(createChatBotMessage, setStateFunc) { this.createChatBotMessage = createChatBotMessage; this.setState = setStateFunc; } handleJavascriptList = () => { const message = this.createChatBotMessage( "Fantastic, I've got the following resources for you on Javascript:", { widget: "javascriptLinks", } ); this.updateChatbotState(message); }; updateChatbotState(message) { // NOTICE: This function is set in the constructor, and is passed in from the top level Chatbot component. The setState function here actually manipulates the top level state of the Chatbot, so it's important that we make sure that we preserve the previous state. this.setState((prevState) => ({ ...prevState, messages: [...prevState.messages, message], })); } } export default ActionProvider; 

    2.  We need to add this method as the handler in the LearningOptions component:

    import React from "react"; import "./LearningOptions.css"; const LearningOptions = (props) => { const options = [ { text: "Javascript", handler: props.actionProvider.handleJavascriptList, id: 1, }, { text: "Data visualization", handler: () => {}, id: 2 }, { text: "APIs", handler: () => {}, id: 3 }, { text: "Security", handler: () => {}, id: 4 }, { text: "Interview prep", handler: () => {}, id: 5 }, ]; const optionsMarkup = options.map((option) => (  {option.text}  )); return {optionsMarkup} ; }; export default LearningOptions; 

    Alright! That was quite a lot of information. But if we now try to click the JavaScript option in the chatbot, we get this result:

    Perfect. But we don't want to stop there, this is a chatbot after all. We want to be able to respond to users who want to use the input field as well. So we need to make a new rule in MessageParser.

    Let's update our MessageParser.js file to look like this:

    class MessageParser { constructor(actionProvider) { this.actionProvider = actionProvider; } parse(message) { const lowerCaseMessage = message.toLowerCase(); if (lowerCaseMessage.includes("hello")) { this.actionProvider.greet(); } if (lowerCaseMessage.includes("javascript")) { this.actionProvider.handleJavascriptList(); } } } export default MessageParser; 

    Now try typing "javascript" into the input field and sending the message. You should get the same list in response from the chatbot.

    So there you have it. We've set up a chatbot that renders a list of possible options and responds to user input.

    For now, we've only set up the bot to handle when someone clicks or types in JavaScript, but you can try to expand the other options on your own. Here's a link to the repository.

    All the code is on GitHub, so feel free to dive into the react-chatbot-kit code or docs.

    Conclusion

    Building things is fun, and a great way to expand your skillset. There are no limits to where you could take this next.

    Perhaps you could make a chatbot that finds the ideal product in webshop based on some simple questions (utilising routing in the app), or maybe you can make one for your company taking care of the most common customer inquiries.

    Feel free to expand, come up with new ideas, and test them out. And if you see something that can be improved, send a pull request.

    Αν θέλετε να βελτιωθείτε ως προγραμματιστής, σας προτείνω να συνεχίσετε να χτίζετε. Είναι πραγματικά το μόνο μονοπάτι προς τα εμπρός. Αν σας άρεσε αυτό το άρθρο και θέλετε να μάθετε πότε δημοσιεύω περισσότερο περιεχόμενο, μπορείτε να με ακολουθήσετε στο Twitter.