← 돌아가기

10. 컨텍스트(원본)


내가 만든 스토리에 다음과 같은 컨텍스트(Context)의 변수활용을 통해서

  • reprompt : 대화노드의 진행상태 관리변수

보다 챗봇을 다양하게 스토리를 구성할 수 있다.
(간단한 프로그래밍적인 요소이기도 하다.)

먼저, reprompt 변수설정하는 사용법은 컨텍스트를 클릭하여 대화정보 에디터를 팝업한 후에 화면의 중간부분에 컨텍스트(CONTEXT)부분의 변수명(Properties)을 클릭하면, 풀다운되어 사용되는 변수들의 리스트가 나타난다. reprompt 변수를 사용하기 위해서 변수리스트 중에서의 reprompt의 왼쪽의 체크박스 를 클릭하면, reprompt 변수와 바로 아래열에 null 이라는 값이 나타난다.  이 null 값을 클릭하면, 다시 변수값의 변수형들 나타나는데 그중에서 boolean 을 선택하면, false가 값이 나타나는데 다시 false를 클릭하고, 다시 나타난 리스트중에서 true 를 선택하여 reprompt의 값을 true로 지정하면 된다. 그리고 대화창 상단의 설정하기 버튼을 클릭하여 저장하면, 에디터화면의 컨텍스트에 {"reprompt":true} 가된다. 그리고 다시 대화정보 표시창을 열고 화면중간부분에 JSON 이란 곳을 클릭하여 보면  {"reprompt":true} 라는 JSON형식의 값이 들어 있음을 알 수 있다.

[TIP] JSON(JavaScript Object Notation)은 프로그램이 서버와 클라이언트가 변수를 주고 받을때, 보편적으로 많이 사용하는 하나의 경량의 DATA-교환 형식 또는 포멧입니다.]

1 . reprompt사용법 (노드의 상태관리)


  • 언제 reprompt를 사용하는가
  • reprompt 사용시 챗봇엔진의 검색방법
에 관한 설명이다.
 
1) 언제 repromt를 사용하는가
 
가끔 일반적인 생활대화상에서도 자주 발생하는 것으로,
 
유저가 마음속에서는
"무엇, 무엇을 해 달라고" 하는데 실질적으로 말할때는
"해달하고"만 말할때가 있다.
 
예를 들면,
A: 저걸로 주세요
    커피, 오렌지중 무슨 메뉴를 드릴까요 : B
A: 커피
    커피를 선택하였습니다. 2,000원 입니다 : B
 
이럴때, 
이를 챗봇엔진의 관점에서 분석을 하면 다음과 같다.
 
A: 그걸로 선택해 주세요 :
    (#주문 --> #주문 노드가 실행됨)
 
   커피, 오렌지중 무슨메뉴를 드릴까요 : B
   ( #주문 또는 #주문 노드의 자식노드중에서 true의 대화표시를 실행하여 답신)
 
A: 커피
   ( @메뉴:커피 --> )
 
  커피를 선택하였습니다. 2,000원 입니다 : B
   (#주문 -- 하위노드중에서 -- @메뉴:커피 의 노드가 실행된 경우)
 
대화중에 , 유저의 질문에 의도만 있고 개체가 없으면 챗봇은 유저의 바라는 질문의 범위가 넓어서 결국은 그 넓은 의도중에서 범위를 축소시키기 위해서 개체를 선택하게끔 하는 돼질문을 하고 다시 대답을 받아서 결국 유저의 정확한 의도+개체 에 부합하는 것에 대응할 수 있다.
 
여기서 주목할 것은
유저의 대화에서 돼질문 후
"커피 " 라고만 했는데
챗봇은 "커피를 선택하였습니다. 2,000원 입니다" 라고 대답할 수 있다.
 
그런데 처음부터 "커피(@메뉴:커피) 선택해 주세요(#주문)"라고 말하면 되는데 일반적으로 
대화중에 #의도+@개체 를 정확하게 하는 경우도 있지만 
그렇지 아니한 #의도 만 있어서 대화중에 우리는 @개체를 지정해 달라(돼질문)고 하는 경우도 많다.
 
이럴때 매대화마다 챗봇엔진에서는 대화의 시작시점(시작하는 노드)인 노드를 지정해주는 즉
대화관리의 상태를 관리해 주어야 한다.
 
따라서, 다시 대화가 실행될때 어떤 노드 부터 시작될 것인가를 
컨텍스트(Context)변수 repromt를 통해서 관리해 주어야 한다.
기본적으로는 루트노드에서 시작한다.
 
2) repromt사용방법
대화진행 중에 필요한 노드에 reprompt 변수에 true 값을 설정해 주어야 한다.
그래야지, 다음에 다시 대화가 실행될 때 다시 지정한 그 노드에서 부터 시작하게 된다.
그렇지 않으면, 챗봇엔진은 항상 루트노드 M에서 부터 시작하여
1차노드부터 먼저 맞는 의도들을 찾게 되고, 선택할 확률이 높다.
 
그러나, 이전대화의 노드에서 reprompt가 true 로 설정되어 있으면,
챗봇엔진이 다음대화에서 루트노드가 아닌 reprompt가 설정된 노드부터 시작하게되며,
그 노드의 다음 하부의 자식노드들 중에서 조건이 맞는 노드를 선택하게 된다.
찾다가 아무것도 없으면 마지막에 설정한 true 노드를 실행하게 된다.
 
이를 챗봇관점의 코드적으로 분석을 하면
아래의 코드에서(RUN대화창의 <> 코드아이콘[닫기버튼바로아래의 <>아이콘]클릭)
conversation_stack의 conversation_node_name : true 인곳에서에서 시작하라는 뜻이다.
즉, #주문 -- true 에서 커피라고 입력 했을때 유저 입력정보이고,
 
 
User Input
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
{
  "story_id": "58e8811665d4404cca9a8760",
  "context": {
    "information": {
      "conversation_stack": [
        {
          "conversation_node": "f7af511c-8700-7152-8868-8cca4e06a1da",
          "conversation_node_name": "true"
        }
      ],
      "user_request_counter": 3,
      "conversation_counter": 3
    },
    "variables": null,
    "reprompt": true,
    "conversation_id": "07bd402b-e329-4ac8-85bf-eef4d1a1732f",
    "input_field": null,
    "retrieve_field": false,
    "visit_counter": 0
  },
  "input": {
    "text": "커피"
  }
}
 
 
"커피~" 라는 선택에 대한 챗봇엔진의 처리정보는 다음과 같다.
아래코드에서 노드가 
 "conversation_node_name": "@메뉴:커피"
가 최종선택되어 실행되었다.
즉, #주문 -- true -- @메뉴:커피 노드가 최종적으로 실행되었지만
이 최종노드에서 스토리를 만들때 특별하게 reprompt를 설정하지 않으면,
챗봇엔진은 reprompt : false 로 초기화 하여 
다음대화에서는 챗봇엔진이 루드노드 부터 시작하게끔 한다.
(즉, 특별히 스토리설계를 강제적으로 reprompt를 true로 값을 설정하지 아니한 이상)
 
 
MIND Understanding
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
47
48
49
50
51
52
53
{
  "intents": [],
  "channel": {
    "user_id": null,
    "channel_id": "mrmind_client"
  },
  "input": {
    "text": "커피"
  },
  "_id": "58ea49e665d440613be875ab",
  "entities": [
    {
      "value": "커피",
      "entity": "메뉴",
      "keyword": "커피"
    }
  ],
  "timeutc": "2017-04-09T14:49:10.577",
  "story_id": "58e8811665d4404cca9a8760",
  "context": {
    "information": {
      "conversation_stack": [
        {
          "conversation_node": "fb05fb56-4e98-719c-9d3b-5dc6170d4d33",
          "conversation_node_name": "@메뉴:커피"
        }
      ],
      "user_request_counter": 4,
      "conversation_counter": 4
    },
    "variables": null,
    "reprompt": false,
    "conversation_id": "07bd402b-e329-4ac8-85bf-eef4d1a1732f",
    "input_field": null,
    "retrieve_field": false,
    "visit_counter": 0
  },
  "time": "2017-04-09T23:49:10.577",
  "output": {
    "visit_nodes_text": [
      "@메뉴:커피 를 선택하셨습니다.<br>(#주문 -- true -- @메뉴 :커피 노드가 실행)<br> (이제 다시 \"커피~\" 그리고 \"커피 메뉴선택 해줘~\" 두개의 질문을 던져서 차이점을 이해해 보세요^^)"
    ],
    "text": [
      "커피 를 선택하셨습니다.<br>(#주문 -- true -- @메뉴 :커피 노드가 실행)<br> (이제 다시 \"커피~\" 그리고 \"커피 메뉴선택 해줘~\" 두개의 질문을 던져서 차이점을 이해해 보세요^^)"
    ],
    "visit_nodes_name": [
      "@메뉴:커피"
    ],
    "visit_nodes": [
      "fb05fb56-4e98-719c-9d3b-5dc6170d4d33"
    ]
  }
}
 
 
따라서 각 대화에서 내가 어떤 노드부터 대화가 시작하는지를
위의  context내의 conversation_stack 정보를 보고서 우리는
판단할 수 있다.
 
  "context": {
    "information": {
      "conversation_stack": [
        {
          "conversation_node": "fb05fb56-4e98-719c-9d3b-5dc6170d4d33",
          "conversation_node_name": "@메뉴:커피"
        }
      ],
 
이와 같이 우리는 reprompt 변수가 대화의 노드진행 상태를 관리하는데 얼마나 중요한 변수 인가를 살펴보았습니다.
이를 참고하여, 스토리를 테스트할 때 코드의 conversation_stack 정보를 잘 살펴보면,
현재 내가 어디서 시작하고 현재 스토리상의 어디에 있는지를 잘 알 수 있다.
 
 
다음은, 챗봇으로 직접
공개챗봇의 "[고급대화] reprompt 변수이용하기" 를 참고하여
테스트 해보세요.