होबोट ढांचे के साथ जटिल चैटबॉट में रूटिंग



कई साल पहले टेलीग्राम के लिए बॉट्स विकसित करना शुरू करने के बाद, मैंने कमांड लाइन इंटरफेस के विशेष मामले के रूप में उनके साथ काम करने के प्रदर्शन, सरलता और लचीलेपन की खोज की। कई लोगों के लिए उपलब्ध ये विशेषताएं, बड़े पैमाने पर लोकप्रिय टेलीग्राफ.जेएस फ्रेमवर्क और पसंद के कारण हैं, जो टेलीग्राम एपीआई के साथ काम करने के लिए सरलीकृत तरीके प्रदान करते हैं।

एक ही समय में परियोजना की वास्तुकला पूरी तरह से डेवलपर के साथ आराम करती है और, जटिल और बहुक्रियाशील बॉट्स की मामूली संख्या को देखते हुए, हमारे पास अभी भी इस संबंध में बढ़ने के लिए जगह है।

इस लेख में मैं एक छोटे से चैटबोट रूटिंग ढांचे के बारे में बात करना चाहता हूं, जिसके बिना हमारी परियोजना का विकास असंभव होगा।

कुछ बुनियादी जानकारी


चैटबॉट और सीएलआई में, एक एकल तार्किक कार्रवाई के निष्पादन में अक्सर कई शोधन चरण या शाखाएं होती हैं। इसके लिए प्रोग्राम को एक निश्चित समन्वय स्थापित करने की आवश्यकता होती है, ताकि यह याद रहे कि प्रवाह में उपयोगकर्ता कहाँ स्थित है और इस निर्देश के अनुसार अपनी कमांड निष्पादित करें।

सबसे सरल चित्रण npm init कमांड का निष्पादन है , जिसके दौरान प्रोग्राम आपको पैकेज के लिए एक या दूसरे डेटा को निर्दिष्ट करने के लिए कहता है। बदले में।

पहले चरण में, वह उपयोगकर्ता को बताती है कि वह पैकेज नाम के पाठ इनपुट के लिए इंतजार कर रही है - और जो उपयोगकर्ता उसे अगले कमांड के साथ भेजता है वह पैकेज नाम के रूप में सहेजा जाएगा, चर के लिए धन्यवाद जिसमें यह प्रतीक्षा लिखी गई है।

इस चर पथ को हम कहते हैं - जिस पथ पर यह या वह कोड तार्किक रूप से जुड़ा हुआ है। यदि बॉट में नेविगेशन या कमांड कुछ चरणों में जारी किए गए हों तो इसकी हमेशा जरूरत होती है।

बॉट आर्किटेक्चर में आज का अभ्यास


अन्य डेवलपर्स द्वारा मैंने पहली बार जिस दृष्टिकोण को देखा, वह इस प्रकार था: उपयोगकर्ता से आने वाले किसी भी अपडेट के लिए, पथ चर के एक विशेष मूल्य के लिए चेक की एक सूची लिखी गई है और व्यावसायिक तर्क और आगे नेविगेशन को इन चेक के अंदर सबसे प्राथमिक रूप में रखा गया है:

onUserInput(ctx, input) {
    switch(ctx.session.path) {
        case 'firstPath':
	    if (input === '!') {
               // -  
	        ctx.reply('!');
	        ctx.session.path = 'secondPath';
	    } else {
	        ctx.reply(' "!"');
	    }
	    break;
        case '...':
       	    //   
    }
}

यदि आपके पास केवल एक टीम है और प्रत्येक टीम के लिए कुछ चरण हैं, तो यह समाधान इष्टतम है। तीसरी टीम और सातवें पर पहुंचना अगर आपको लगता है कि कुछ गलत हो रहा है।

बॉट्स में से एक में हमें देर से मंच पर काम करने का मौका मिला, कार्यात्मक का मूल 4000 पंक्तियों की एक शीट थी और ~ शीर्ष स्तर की केवल 70 स्थितियां जो दो दिलों से बढ़ीं, जो दिल में गईं, कभी-कभी रास्ते, कभी-कभी आदेशों की जांच के साथ। कभी-कभी रास्ते और आदेश। इन सभी शर्तों को प्रत्येक उपयोगकर्ता कार्रवाई के लिए जांचा गया था और पड़ोसी शीट ऑब्जेक्ट से सहायक कार्यों को एक्सेस किया गया था, जो कई लाइनों से भी बढ़ गया था। यह कहने की आवश्यकता नहीं है कि यह परियोजना कितनी धीमी और स्पष्ट थी?

होबोट ढांचा


एक्चुलाइज़बॉट शुरू करते हुए , हमने पहले से ही कल्पना की थी कि यह कितना बड़ा होगा, और हमारा पहला काम विकास की व्यापकता और गति को संरक्षित करना था।

ऐसा करने के लिए, हमने क्लाइंट लॉजिक को रास्तों को सौंपे गए नियंत्रकों में तोड़ दिया और इन नियंत्रकों के बीच नेविगेट करने और उनमें उपयोगकर्ता से प्राप्त संदेशों को संसाधित करने के लिए एक छोटा अमूर्त पत्र लिखा।

यह सब, बड़ी परियोजनाओं पर आधारित, टाइपस्क्रिप्ट में लिखा गया था और सुरुचिपूर्ण नाम हॉबोट प्राप्त हुआ, जो संकेत देता है, ज़ाहिर है, नेविगेशन पाइपलाइनों पर।

एक नियंत्रक तीन गुणों की एक सरल वस्तु है:

  • पथ - प्रारंभिक पथ को पहचानने और नेविगेट करने के लिए उपयोग किए जाने वाले पथ के स्ट्रिंग पहचानकर्ता
  • get — , , hobot.gotoPath(ctx, path, data?). — data ,
  • post — . , , . updateType — , : text, callback_query . updateType ctx

नियंत्रक उदाहरण:

const anotherController = {
    path: 'firstPath',
    get: async (ctx, data) => 
        await ctx.reply('Welcome to this path! Say "Hi"'),
    post: async (ctx, updateType) => {
        //     : text / callback_query / etc...
        if (updateType === updateTypes.text && ctx.update.message.text === 'Hi') {
            await ctx.reply("Thank you!");
            // hobot       this:
            this.hobot.gotoPath(ctx, 'secondPath', { userJustSaid: "Hi" });
        } else {
            //     ,       
            await ctx.reply('We expect "Hi" text message here');
        }
    }
}

यह शुरुआत की तुलना में थोड़ा अधिक जटिल लगता है, लेकिन कठिनाई तब भी रहेगी जब आपके पास 100 या 200 रास्ते होंगे।

आंतरिक तर्क तुच्छ है और यह आश्चर्य की बात है कि किसी ने अभी तक ऐसा नहीं किया है :
इन नियंत्रकों को एक ऑब्जेक्ट में जोड़ा जाता है, जिनकी कुंजी पथ संपत्ति के मूल्य हैं और उपयोगकर्ता क्रियाओं के दौरान इन चाबियों से इसे बुलाया जाता है या hobot .gotoPath (ctx, path, data) का उपयोग करते हुए नेविगेट करते हैं ? ) का है

नेविगेशन को चर पथ और नेविगेशन तर्क को नहीं छूने के लिए एक अलग विधि में आवंटित किया गया है, लेकिन केवल व्यावसायिक तर्क के बारे में सोचने के लिए, हालांकि आप हमेशा अपने हाथों से ctx.session.path बदल सकते हैं, जो निश्चित रूप से अनुशंसित नहीं है।

अविनाशी संरचना कार्य के साथ अपने नए बॉट को बनाने के लिए आपको बस एक नियमित टेलीग्राफ बॉट लॉन्च करना होगा और इसे पास करना होगा और होब कंस्ट्रक्टर को कॉन्फिगर करना होगा। कॉन्फ़िगरेशन ऑब्जेक्ट में नियंत्रकों को शामिल करना होता है जिसे आप प्रारंभ करना चाहते हैं, डिफ़ॉल्ट पथ, और कमांड / कंट्रोलर जोड़े।

//   telegraf-
const bot = new Telegraf('_');

//  
export const hobot = new Hobot(bot, {
    defaultPath: 'firstPath',
    commands: [
        //  ,     
        // get    :
        { command: 'start', path: 'firstPath' }
    ],
    controllers: [
        // -,    
        startController,
        nextController
    ]
});

// C telegraf-,       
bot.launch();

निष्कर्ष के तौर पर


नियंत्रक में एक शीट को विभाजित करने के निहित लाभ:

  • अलग-अलग कार्यों, विधियों और इंटरफेस को रखने की क्षमता जो नियंत्रक के बगल में अलग-अलग फ़ाइलों में इस नियंत्रक के तर्क पर लॉक होती है
  • गलती से सब कुछ टूटने का खतरा कम हो गया
  • प्रतिरूपकता: श्रोताओं के एक निश्चित सेगमेंट को चालू / बंद करना या यह तर्क देना बस एरे से कंट्रोलर को जोड़कर और हटाकर किया जा सकता है, जिसमें बिना प्रोग्रामिंग को कॉन्फ़िगर किए अपडेट को अपडेट करना भी शामिल है - इसके लिए, निश्चित रूप से, हमें कुछ अक्षरों को लिखने की जरूरत है, क्योंकि हमने अभी तक नहीं किया है। पहुंच गए
  • उपयोगकर्ता को स्पष्ट रूप से यह बताने की क्षमता कि उससे क्या उम्मीद की जाती है जब वह (जो अक्सर होता है) कुछ गलत करता है - और इसे करें जहां यह जगह है - पोस्ट विधि प्रसंस्करण के अंत में

हमारी योजनाएं :

यह लेख टेक्स्ट मैसेजिंग होबॉट के साथ काम करने के लिए मूल स्क्रिप्ट का वर्णन करता है।
यदि विषय प्रासंगिक हो जाता है, तो हम भविष्य के लेखों में टेलीग्राम बॉट्स को विकसित करने और उपयोग करने के अभ्यास से फ्रेमवर्क की अन्य तकनीकी सूक्ष्मताओं और हमारी टिप्पणियों को साझा करेंगे।

लिंक :

बॉट स्थापित करना इस तरह दिखता है: README.MD में वॉकथ्रू के साथ npm i -s hobot
रिपोजिटरी और होबॉट पर आधारित उत्पादन में काम करने वाले सैंडबॉक्स
रेडी बॉट

आपका ध्यान के लिए धन्यवाद, मुझे नए बॉट के लिए आपके प्रश्न, सुझाव या विचार सुनने में खुशी होगी!

All Articles