Како направити Цхатбот са Реацт-ом

Моја филозофија је једноставна. Да бисте постали добри у нечему, морате то много да урадите.

Није довољно то учинити једном. Морате то поновити, и опет и опет. Никада се неће завршити. Користила сам исту филозофију да бих се добро усавршила у програмирању.

Једна ствар коју сам приметио на овом путовању је да је много забавније градити ствари које су занимљиве и које добро изгледају. Ствари које можете показати пријатељима и бити поносни на њих. Нешто што вас узбуђује када започнете када седнете испред тастатуре.

Због тога сам направио цхатбот.

Који се претворио у нпм пакет.

Па хајде да заједно направимо један. Ако желите сами да се носите са овим изазовом, можете директно да пређете на документацију (која је заправо цхатбот). Или, ако сте визуелни ученик, креирао сам водич на ИоуТубе-у.

Иначе, идемо. Претпоставићу да имате инсталиран Ноде и приступ наредби нпк. Ако не, иди по њега овде.

Почетно подешавање

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

Ово би требало да инсталира нпм пакет и отвори развојни сервер на лоцалхост: 3000.

Следеће идите App.jsи унесите следеће промене:

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

Одличан посао. Стижемо тамо. Ово бисте сада требали видети на свом развојном серверу:

Цхатбот узима три реквизита која морају бити укључена да би могао да функционише. Прво, потребна му је конфигурација која мора да садржи initialMessagesсвојство са објектима поруке цхатбот-а.

Друго, потребна му је MessageParserкласа која мора да примени метод рашчлањивања.

Треће, потребна му је ActionProviderкласа која ће применити радње које желимо да предузмемо на основу рашчлањивања поруке.

Касније ћемо ући дубље у ово. За сада идите овде да бисте започели шифру узорка.

  • Ставите 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 ( ); }

Ово би сада требало да видите на лоцалхост: 3000:

Слатко. Сада смо цхатбот приказали на екрану и можемо писати у поље за унос и предати га како бисмо послали поруку у цхат. Али када то покушамо, ништа се не дешава.

Разумевање како цхатбот ради

Овде морамо да зауставимо и погледамо како MessageParserи како ActionProviderкомуницирају да би наш бот кренуо у акцију.

Када се бот иницијализује, initialMessagesсвојство из конфигурације се ставља у интерно стање цхатбота у својству које се зове messages, а које се користи за приказивање порука на екрану.

Штавише, када напишемо и притиснемо дугме за слање у пољу за ћаскање, наш MessageParser(који смо проследили као реквизите цхатботу) позива своју parseметоду. Због тога се овај метод мора применити.

Погледајмо ближе MessageParserпочетни код:

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

Ако пажљиво погледамо, овај метод је конструисан са actionProvider. Ово је иста ActionProviderкласа коју предајемо цхатботу као реквизите. То значи да контролишемо две ствари - како се порука рашчлањује и које акције треба предузети на основу поменутог рашчлањивања.

Искористимо ове информације да креирамо једноставан цхатбот одговор. Прво измените 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

Леп. Сад ако у поље за ћаскање укуцамо „здраво“, добићемо ово назад:

Фантастичан. Сада када можемо да контролишемо рашчлањивање поруке и одговарање акцијом, покушајмо да учинимо нешто сложенијим. Покушајмо да направимо бота који ће вам пружити ресурсе за учење програмског језика који тражите.

Израда бота за учење

Прво, вратимо се нашој 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

ОК, овде смо додали нека својства и променили почетну поруку. Најважније је да смо боту дали име и променили боју messageboxи chatbuttonкомпонената.

У реду. Сада прелазимо на добар део.

Не само да можемо рашчланити поруке и одговорити кориснику поруком цхатбота, већ можемо дефинисати прилагођене компоненте Реацт које желимо да прикажемо уз поруку. Ове компоненте могу бити све што пожелимо - то су обичне старе Реацт компоненте.

Испробајмо је тако што ћемо створити компоненту опција која ће корисника водити до могућих опција.

Прво дефинишемо компоненту опција учења:

// 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; }

Сада када имамо своју компоненту, морамо је регистровати код свог цхатбота. Пређите на config.jsи додајте следеће:

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) => , }, ], }

Разумевање виџета

У реду. Дајмо одушка и истражимо шта смо урадили.

  1. Направили смо LearningOptionsкомпоненту.
  2. Компоненту смо регистровали widgetsу нашој конфигурацији.
  3. Дали смо createChatbotMessageфункцији објект опција који одређује који ће виџет приказати уз ову поруку.

Резултат:

Фантастично, али зашто смо морали да региструјемо нашу компоненту у конфигурацији као функцију виџета?

Давањем функције, ми контролишемо када извршавамо позивање. То нам омогућава простор за украшавање виџета важним својствима унутар цхатбота.

Виџет који дефинишемо примиће одређена својства од цхатбота (од којих нека могу да контролишу конфигурациона својства):

  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.

    Ако желите да се побољшате као програмер, подстичем вас да наставите да градите. То је заиста једини пут напред. Ако вам се свидео овај чланак и желите да знате када објавим још садржаја, можете ме пратити на Твиттер-у.