Watson์œผ๋กœ ์‰ฝ๊ฒŒ ๋งŒ๋“œ๋Š” ์นด์นด์˜คํ†ก ChatBot

์ด ํฌ์ŠคํŒ…์€ 3. ๋Œ€ํ™” ๋‚ด์šฉ์œผ๋กœ ํšŒ์˜์‹ค ์˜ˆ์•ฝํ•˜๊ธฐ์— ์ด์–ด์ง€๋Š” ํฌ์ŠคํŒ…์ž…๋‹ˆ๋‹ค. ์ด ๋‹จ๊ณ„์—์„œ๋Š” ์–ดํ”Œ๋ฆฌ์ผ€์ด์…˜์„ ์นด์นด์˜คํ†ก๊ณผ ์—ฐ๋™ํ•˜๊ธฐ ์œ„ํ•œ API๋ฅผ ์ƒ์„ฑํ•ฉ๋‹ˆ๋‹ค.

< ์ด ํฌ์ŠคํŒ…๊ณผ ์—ฐ๊ฒฐ๋œ ๊ธ€ ๋ชฉ๋ก >

4. Node.js ์–ดํ”Œ๋ฆฌ์ผ€์ด์…˜ ์นด์นด์˜คํ†ก๊ณผ ์—ฐ๋™ํ•˜๊ธฐ

4.1 ์˜๋กœ์•„์ด๋”” ์ƒ์„ฑ

์นด์นด์˜คํ†ก์€ ์˜๋กœ์•„์ด๋””๋ผ๋Š” ์„œ๋น„์Šค๋ฅผ ์ œ๊ณตํ•˜๊ณ  ์žˆ๋Š”๋ฐ, ์ด ์„œ๋น„์Šค๋ฅผ ํ†ตํ•ด์„œ ํ”Œ๋Ÿฌ์Šค์นœ๊ตฌ๋ฅผ ์ƒ์„ฑํ•  ์ˆ˜ ์žˆ์Šต๋‹ˆ๋‹ค. ์˜๋กœ์•„์ด๋””์˜ ์ƒ์„ฑ์€ ์นด์นด์˜คํ†ก ์˜๋กœ์•„์ด๋”” ๊ณต์‹ ํ™ˆํŽ˜์ด์ง€๋ฅผ ํ†ตํ•ด ๊ฐ€๋Šฅํ•˜๋ฉฐ ์„œ๋น„์Šค ๊ด€๋ฆฌ์ž์˜ ์Šน์ธ ํ›„ ์™„๋ฃŒ๋˜๋Š”๋ฐ 2-3์ผ์—์„œ ์ตœ๋Œ€ ์ผ์ฃผ์ผ ์†Œ์š”๋œ๋‹ค๊ณ  ํ•ฉ๋‹ˆ๋‹ค. ์ €์˜ ๊ฒฝ์šฐ๋Š” 2์ผ์ •๋„ ๊ฑธ๋ ธ์Šต๋‹ˆ๋‹ค.

์˜๋กœ์•„์ด๋”” ์ƒ์„ฑ์ด ์™„๋ฃŒ๋œ ํ›„์—๋Š” ๋‚ด ์˜๋กœ์•„์ด๋”” ๊ด€๋ฆฌ ํ™”๋ฉด์„ ์‚ฌ์šฉํ•  ์ˆ˜ ์žˆ์Šต๋‹ˆ๋‹ค. ๊ด€๋ฆฌํ™”๋ฉด์˜ ์ขŒ์ธก์— ๋ณด๋ฉด ์ž๋™ ์‘๋‹ต์ด๋ž€ ๋ฉ”๋‰ด๊ฐ€ ์žˆ๋Š”๋ฐ, ์šฐ๋ฆฌ๋Š” ์ด ๊ธฐ๋Šฅ์„ ์‚ฌ์šฉํ•˜์—ฌ Watson Converation๊ณผ ์—ฐ๋™ํ•  ๊ฒƒ์ž…๋‹ˆ๋‹ค.

์นด์นด์˜คํ†ก์˜ ์˜๋กœ์•„์ด๋””๋Š” 1๊ฐœ์˜ ๋ฉ”์„ธ์ง€์— ๋Œ€ํ•ด 1๊ฐœ์˜ ์‘๋‹ต์„ ์„ค์ •ํ•  ์ˆ˜ ์žˆ์Šต๋‹ˆ๋‹ค. ๋‹ค์‹œ ๋งํ•˜๋ฉด, ์‚ฌ์šฉ์ž๊ฐ€ ์นด์นด์˜คํ†ก์„ ํ†ตํ•ด ๋ง์„ ๊ฑธ๋ฉด ๊ทธ์— ๋Œ€ํ•œ ์‘๋‹ต์„ ํ•˜๋„๋ก ์„ค์ •์ด ๊ฐ€๋Šฅํ•ฉ๋‹ˆ๋‹ค. ๋ฐ˜๋Œ€๋กœ ์„œ๋น„์Šค๊ฐ€ ๋จผ์ € ๋ง์„ ๊ฑธ๋„๋ก ์„ค์ •ํ•˜๋Š” ๊ฒƒ์€ ์นด์นด์˜คํ†ก์— ๋ฌธ์˜ํ•œ ๊ฒฐ๊ณผ ์˜๋กœ์•„์ด๋””๊ฐ€ ์•„๋‹Œ ์นด์นด์˜คํ†ก ๋น„์ฆˆ๋ฉ”์„ธ์ง€๋ฅผ ํ†ตํ•ด์„œ ๊ฐ€๋Šฅํ•˜๋‹ค๊ณ  ํ•ฉ๋‹ˆ๋‹ค. ํ˜น์‹œ ๊ด€๋ จ ๊ธฐ๋Šฅ์— ๊ด€์‹ฌ์ด ์žˆ์œผ์‹  ๋ถ„์€ ๋น„์ฆˆ๋ฉ”์„ธ์ง€ ์„œ๋น„์Šค๋ฅผ ์ฐธ์กฐํ•˜์‹ญ์‹œ์˜ค.

4.2 ์นด์นด์˜คํ†ก ์—ฐ๋™์„ ์œ„ํ•œ ํ…Œ์ŠคํŠธ API ์ƒ์„ฑ

์ด ํŠœํ† ๋ฆฌ์–ผ์€ 3. ๋Œ€ํ™” ๋‚ด์šฉ์œผ๋กœ ํšŒ์˜์‹ค ์˜ˆ์•ฝํ•˜๊ธฐ์— ์ด์–ด์ง‘๋‹ˆ๋‹ค. Tutorial 3์„ ์™„๋ฃŒํ•˜์ง€ ๋ชปํ•˜์‹  ๋ถ„์€ tutoral4๋ฅผ checkout ํ•ฉ๋‹ˆ๋‹ค.

git checkout tutorial4

์นด์นด์˜คํ†ก๊ณผ ์—ฐ๋™์„ ํ…Œ์ŠคํŠธํ•˜๊ธฐ ์œ„ํ•ด dummy API๋ฅผ ์ƒ์„ฑํ•ฉ๋‹ˆ๋‹ค.

์นด์นด์˜คํ†ก์˜ ์ž๋™์‘๋‹ต ์„œ๋น„์Šค์™€ ์—ฐ๋™ํ•˜๊ธฐ ์œ„ํ•ด์„œ๋Š” /keyboard ์™€ /message API๋ฅผ ๊ตฌํ˜„ํ•ด์•ผํ•ฉ๋‹ˆ๋‹ค.

1) /api ๋ฐ‘์— kakao ํด๋”๋ฅผ ์ƒ์„ฑํ•ฉ๋‹ˆ๋‹ค.

2) /api/kakao ๋ฐ‘์— keyboard.js๋ฅผ ์ƒ์„ฑํ•˜๊ณ  ๋‹ค์Œ ์ฝ”๋“œ๋ฅผ ์ž…๋ ฅํ•ฉ๋‹ˆ๋‹ค.

'use strict';

let getKeyboard = (req, res) => {
  res.setHeader('Content-Type', 'application/json; charset=utf-8');

  return res.json({
    "type" : "text"
  })
};

module.exports = {
  'initialize': function(app, options) {
    app.get('/api/kakao/keyboard', getKeyboard);
  }
};

3) /api/kakao ๋ฐ‘์— message.js๋ฅผ ์ƒ์„ฑํ•˜๊ณ  ๋‹ค์Œ ์ฝ”๋“œ๋ฅผ ์ž…๋ ฅํ•ฉ๋‹ˆ๋‹ค.

'use strict';

let postMessage = (req, res) => {
  res.setHeader('Content-Type', 'application/json; charset=utf-8');

  return res.json({
    "message" : {
      "text" : "test"
      }
  })
};

module.exports = {
    'initialize': function(app, options) {
        app.post('/api/kakao/message', postMessage);
    }
};

4) /api/index.js๋ฅผ ์•„๋ž˜์™€ ๊ฐ™์ด ์ˆ˜์ •ํ•ฉ๋‹ˆ๋‹ค. ๊ตต์€๊ธ€์”จ๋กœ ๋œ ์ฝ”๋“œ๋ฅผ ์ถ”๊ฐ€ํ•ฉ๋‹ˆ๋‹ค.

'use strict';

console.log('APIs initialize');

const conversation = require('./message');
const kakao_keyboard = require('./kakao/keyboard');
const kakao_message = require('./kakao/message');

module.exports = {
    'initialize': (app, options) => {
        conversation.initialize(app, options);
        kakao_keyboard.initialize(app, options);
        kakao_message.initialize(app, options);
    }
};

5) ์ˆ˜์ •ํ•œ ์ฝ”๋“œ๋ฅผ ๋ธ”๋ฃจ๋ฏน์Šค์— ๋””ํ”Œ๋กœ์ดํ•ฉ๋‹ˆ๋‹ค. ํ”„๋กœ์ ํŠธ์˜ ์ตœ์ƒ์œ„ ํด๋”์—์„œ ๋‹ค์Œ ๋ช…๋ น์„ ์ˆ˜ํ–‰ํ•ฉ๋‹ˆ๋‹ค.

cf push

4.3 ์˜๋กœ์•„์ด๋””๋กœ ์ž๋™์‘๋‹ต ์„ค์ •ํ•˜๊ธฐ

yellowid03

์นด์นด์˜คํ†ก ์˜๋กœ์•„์ด๋””์˜ ์ž๋™์‘๋‹ต ๊ธฐ๋Šฅ์€ ํ‚ค์›Œ๋“œํ˜• ์ž๋™์‘๋‹ต๊ณผ APIํ˜• ์ž๋™์‘๋‹ต์ด ์žˆ์Šต๋‹ˆ๋‹ค. ์šฐ๋ฆฌ๋Š” ์šฐ์ธก์— ์œ„์น˜ํ•œ APIํ˜• ์ž๋™์‘๋‹ต์„ ํ†ตํ•ด ์„œ๋น„์Šค๋ฅผ ์—ฐ๋™ ํ•˜๋ คํ•ฉ๋‹ˆ๋‹ค.
์„ค์ •ํ•˜๊ธฐ ๋ฒ„ํŠผ์„ ๋ˆŒ๋Ÿฌ ์„ค์ •์„ ์‹œ์ž‘ํ•ฉ๋‹ˆ๋‹ค.

์ œ๊ฐ€ ์„ค์ •ํ•œ ์ •๋ณด๋ฅผ ์ฐธ์กฐํ•˜๋˜ App URL์—๋Š” ๊ฐ์ž์˜ url ๋’ค์— /api/kakao๋ฅผ ๋ถ™์—ฌ ์ž…๋ ฅํ•˜์‹ญ์‹œ์˜ค.

yellowid04

API ํ…Œ์ŠคํŠธ ๋ฒ„ํŠผ์„ ํด๋ฆญํ•˜์—ฌ ์ •์ƒ ๋™์ž‘์„ ํ™•์ธํ•ฉ๋‹ˆ๋‹ค.
์„ค์ •์„ ์™„๋ฃŒํ•œ ๋’ค์—๋Š” ์„œ๋น„์Šค ์‹œ์ž‘ ๋ฒ„ํŠผ์„ ๋ˆŒ๋Ÿฌ ์„œ๋น„์Šค๋ฅผ ์‹œ์ž‘ํ•ฉ๋‹ˆ๋‹ค.

์„ค์ •์„ ํ…Œ์ŠคํŠธ ํ•˜๊ธฐ ์œ„ํ•ด์„œ๋Š” ์นด์นด์˜คํ†ก์—์„œ ํ”Œ๋Ÿฌ์Šค ์นœ๊ตฌ๋ฅผ ๋“ฑ๋กํ•œ ํ›„ ์•„๋ž˜ ์Šคํฌ๋ฆฐ์ƒท์ฒ˜๋Ÿผ ์•„๋ฌด ๋ฉ”์„ธ์ง€๋‚˜ ๋‚จ๊ฒจ๋ด…๋‹ˆ๋‹ค.

KakaoTalk_20170219_205430774

4.4 Watson Conversation๊ณผ ์นด์นด์˜คํ†ก ์—ฐ๋™ํ•˜๊ธฐ

์ด ๋‹จ๊ณ„์—์„œ๋Š” Watson Conversation๊ณผ ์นด์นด์˜คํ†ก api๋ฅผ ์—ฐ๊ฒฐํ•˜๊ธฐ ์œ„ํ•ด ๊ฐ api์˜ input/output์„ ๋งž์ถฐ์ค๋‹ˆ๋‹ค. /api/kakao/message.js๋ฅผ ์ˆ˜์ •ํ•˜์—ฌ ์นด์นด์˜คํ†ก์œผ๋กœ ๋ถ€ํ„ฐ ์˜ค๋Š” ๋ฉ”์„ธ์ง€๋ฅผ Watson Conversation ์„œ๋น„์Šค์˜ input์œผ๋กœ ํ•˜๊ณ  Watson Conversation ์„œ๋น„์Šค์˜ output์„ response๋กœ ํ•˜์—ฌ ์นด์นด์˜คํ†ก์˜ ์‘๋‹ต์œผ๋กœ ๋…ธ์ถœ๋˜๋„๋ก ์„ค์ •ํ•ฉ๋‹ˆ๋‹ค. ์ด ๊ณผ์ •์—์„œ context๋ฅผ ์œ ์ง€ํ•˜๊ธฐ ์œ„ํ•ด, ์นด์นด์˜คํ†ก api๊ฐ€ ์ฃผ๋Š” user_key ๊ฐ’์„ id๋กœ ํ•˜์—ฌ context๋ฅผ cloudant์— ์ €์žฅํ•ฉ๋‹ˆ๋‹ค.

1) ๋จผ์ € .env ํŒŒ์ผ์— cloudant์˜ credential ์ •๋ณด๋ฅผ ์„ค์ •ํ•ฉ๋‹ˆ๋‹ค. cloudant์˜ credential ์ •๋ณด ์ค‘ cloudantUrl์€ cloudant์— ์ ‘๊ทผํ•  ์ˆ˜ ์žˆ๋Š” url์„, cloudantDB๋Š” database ์ด๋ฆ„์„ ์˜๋ฏธํ•ฉ๋‹ˆ๋‹ค. cloudantUrl ๊ฐ’์€ Bluemix dashboard์—์„œ Cloudant ์„œ๋น„์Šค๋ฅผ ์„ ํƒํ•œ ํ›„ ์„œ๋น„์Šค ์‹ ์ž„ ์ •๋ณด ๋ฉ”๋‰ด๋ฅผ ํ†ตํ•ด ํ™•์ธํ•  ์ˆ˜ ์žˆ์Šต๋‹ˆ๋‹ค. cloudantDB์˜ ๊ฐ’์€ ์˜ˆ์‹œ์™€ ๋™์ผํ•˜๊ฒŒcontext๋กœ ์„ค์ •ํ•ฉ๋‹ˆ๋‹ค.

# Cloudant
CLOUDANT_URL=https://XXXXXX-XXXX-XXXX-XXXX-XXXXXXXXXX-bluemix:XXXXXXXXXXXX@XXXXXX-XXXX-XXXX-XXXX-XXXXXXXXXX-bluemix.cloudant.com
CLOUDANT_CONTEXT_DB=context

2) /util/db.js๋ฅผ ํ™•์ธํ•ฉ๋‹ˆ๋‹ค. ์ด์ „ ๋‹จ๊ณ„์—์„œ ์„ค์ •ํ•œ ํ™˜๊ฒฝ๋ณ€์ˆ˜๋ฅผ ์ด์šฉํ•˜์—ฌ database๋ฅผ ์ƒ์„ฑํ•˜๊ณ  ์—ฐ๊ฒฐํ•˜๋„๋ก ๋˜์–ด์žˆ์Šต๋‹ˆ๋‹ค.

process.env.CLOUDANT_URL
process.env.CLOUDANT_CONTEXT_DB

3) /api/kakao/message.js๋ฅผ ์ˆ˜์ •ํ•˜์—ฌ Conversation Service๋ฅผ ํ˜ธ์ถœํ•˜๋„๋ก ๊ตฌํ˜„ํ•ฉ๋‹ˆ๋‹ค. ๋จผ์ € ํŒŒ์ผ ์ƒ๋‹จ์— ํ•„์š”ํ•œ module์„ import ํ•ฉ๋‹ˆ๋‹ค.

const conversation = require('../message');
const cloudant = require('../../util/db');
const db = cloudant.db;

4) postMessage() ํ•จ์ˆ˜๋ฅผ ๋‹ค์Œ๊ณผ ๊ฐ™์ด ์ˆ˜์ •ํ•ฉ๋‹ˆ๋‹ค.

let postMessage = (req, res) => {
  res.setHeader('Content-Type', 'application/json; charset=utf-8');

  //{ user_key: 'DBpb8t6y66U2', type: 'text', content: 'Hello' }
  let user_key = req.body.user_key;
  let type = req.body.type;
  let content = {
    'text' : req.body.content
  };

  //user_key๋ฅผ ์‚ฌ์šฉํ•˜์—ฌ db์— ์ €์žฅ๋œ context๊ฐ€ ์žˆ๋Š”์ง€ ํ™•์ธํ•ฉ๋‹ˆ๋‹ค.
  db.get(user_key).then(doc => {
    //์ €์žฅ๋œ context๊ฐ€ ์žˆ๋Š” ๊ฒฝ์šฐ ์ด๋ฅผ ์‚ฌ์šฉํ•˜์—ฌ conversation api๋ฅผ ํ˜ธ์ถœํ•ฉ๋‹ˆ๋‹ค.
    conversation.getConversationResponse(content, doc.context).then(data => {
      // context๋ฅผ ์—…๋ฐ์ดํŠธ ํ•ฉ๋‹ˆ๋‹ค.
      db.insert(Object.assign(doc, {
        'context': Object.assign(data.context, {
          'timezone' : "Asia/Seoul"
        }),
      }));

      return res.json({
        "message" : {
          "text" : getOutputText(data)
        }
      });
    }).catch(function(err){
      return res.json({
          "message" : {
            "text" : JSON.stringify(err.message)
          }
      });
    });
  }).catch(function(err) {
    // ์ฒ˜์Œ ๋Œ€ํ™”์ธ ๊ฒฝ์šฐ context๊ฐ€ ์—†์Šต๋‹ˆ๋‹ค. ์ด๋Ÿฌํ•œ ๊ฒฝ์šฐ context ์—†์ด conversation api๋ฅผ ํ˜ธ์ถœํ•ฉ๋‹ˆ๋‹ค.
    conversation.getConversationResponse(content, {}).then(data => {
      // context๋ฅผ ์ €์žฅํ•ฉ๋‹ˆ๋‹ค.
      db.insert({
        '_id' : user_key,
        'user_key' : user_key,
        'context': data.context,
        'type' : 'kakao'
      });
          
      return res.json({
          "message" : {
            "text" : getOutputText(data)
          }
      });   
    }).catch(function(err){
      return res.json({
          "message" : {
            "text" : JSON.stringify(err.message)
          }
      });
    });
    
  });
};

5) getOutputText() ํ•จ์ˆ˜๋ฅผ ์ถ”๊ฐ€ํ•ฉ๋‹ˆ๋‹ค. ์นด์นด์˜คํ†ก์˜ api ํฌ๋งท์— ๋งž์ถ”๊ธฐ ์œ„ํ•ด conversation์ด ์ฃผ๋Š” Array ํƒ€์ž…์˜ output.text์—์„œ String ๊ฐ’์„ ์ถ”์ถœํ•ฉ๋‹ˆ๋‹ค.

let getOutputText = data => {
  let output = data.output;
  if(output.text && Array.isArray(output.text)){
    return output.text.join('\\n');
  }
  else if(output.text){
    return output.text;
  }
  else return "";
}

4.5 ์นด์นด์˜คํ†ก์œผ๋กœ ํ…Œ์ŠคํŠธํ•˜๊ธฐ

์ฝ”๋“œ์ž‘์„ฑ์ด ์™„๋ฃŒ๋˜์—ˆ์œผ๋ฉด ์นด์นด์˜คํ†ก์œผ๋กœ ๋‹ค์Œ๊ณผ ๊ฐ™์ด ํ…Œ์ŠคํŠธํ•ฉ๋‹ˆ๋‹ค.

KakaoTalk_20170219_205418205

์ด์–ด์ง€๋Š” ํฌ์ŠคํŒ…์€

Watson์œผ๋กœ ์‰ฝ๊ฒŒ ๋งŒ๋“œ๋Š” ์นด์นด์˜คํ†ก ChatBot 5. [์‘์šฉ] ํšŒ์˜์‹ค ์˜ˆ์•ฝ ์กฐํšŒ ๋ฐ ์ทจ์†Œ ๊ธฐ๋Šฅ ์ถ”๊ฐ€ํ•˜๊ธฐ

์ž…๋‹ˆ๋‹ค.