RASA - Session persistence
Tags: rasa, chatbot, nlp, ai
Published: 2022-07-28 08:41:14

In this article, we will add session persistence to the web chat application created in the [previous post](https://dev.to/petr7555/rasa-socket-io-integration-pfo). This will allow a user to continue in the conversation with the chatbot even after a browser tab / window is closed.

First, we need to enable session persistence in the Rasa chatbot project. Set `session_persistence` to `true`.

```yml
# credentials.yml
socketio:
  user_message_evt: user_uttered
  bot_message_evt: bot_uttered
  session_persistence: true
```

Now the frontend will be responsible for generating a session ID and sending it to the Rasa server. It needs to emit a `session_request` event with `session_id` immediately after the `connect` event.

We'll manage the session ID by storing it in the [`localStorage`](https://developer.mozilla.org/en-US/docs/Web/API/Window/localStorage).

```js
function getSessionId() {
    const storage = localStorage;
    const storageKey = 'RASA_SESSION_ID';
    const savedId = storage.getItem(storageKey);
    if (savedId) {
        return savedId;
    }
    const newId = socket.id;
    storage.setItem(storageKey, newId);
    return newId;
}
```

The function `getSessionId` returns a session ID stored in the `localStorage`. If there is no such ID, it creates a new one, stores it in the `localStorage` and returns it. The session ID can be any `string` (`number` does not work) unique to every user (website visitor). [`socket.id`](https://socket.io/docs/v4/server-socket-instance/#socketid) is a good candidate.

Now when we have the `getSessionId` function, we can use it to get a session ID and send it immediately after the `connect` event. Change the `connect` event handler in `index.html` to the following:

```js
socket.on('connect', function () {
    console.log('Connected to Socket.io server.');
    socket.emit('session_request', {
        'session_id': getSessionId(),
    });
    console.log(`Session ID: ${getSessionId()}`);
});
```

The same session ID must be sent with every `user_uttered` event. The event is emitted in two places:
1. in the `appendQuickReplies` function when the quick reply button is clicked and 
2. when the form is submitted, i.e. when a user clicks _Send_.

We'll create a function `utter(msg)` that will send a message passed as a parameter and the session ID.

```js
function utter(msg) {
    socket.emit('user_uttered', {
        'message': msg,
        'session_id': getSessionId(),
    });
}
```

Lastly, we will replace the two mentioned occurrences of the `user_uttered` event with calls to the `utter` function.

```js
function appendQuickReplies(quickReplies) {
    const quickRepliesNode = document.createElement('div');
    quickRepliesNode.classList.add('quick-replies');
    quickReplies.forEach(quickReply => {
        const quickReplyDiv = document.createElement('button');
        quickReplyDiv.innerHTML = quickReply.title;
        quickReplyDiv.classList.add('button');
        quickReplyDiv.addEventListener('click', () => {
            messages.removeChild(quickRepliesNode);
            appendMessage(quickReply.title, 'sent');
            /** NEW CODE **/
            utter(quickReply.payload);
            /** ******** **/
        });
        quickRepliesNode.appendChild(quickReplyDiv);
    });
    messages.appendChild(quickRepliesNode);
    scrollToBottom();
}
```

```js
form.addEventListener('submit', function (e) {
    e.preventDefault();
    const msg = messageInput.value;
    if (msg) {
        /** NEW CODE **/
        utter(msg);
        /** ******** **/
        messageInput.value = '';

        appendMessage(msg, 'sent');
    }
});
```

## Run the application
1. Serve the application on `http://localhost:8080` by running `npx http-server webchat`.
2. In a new terminal window, run the rasa server with enabled cors for all origins: `rasa run --cors "*"`.
3. In another terminal window, run the actions server: `rasa run actions`.
4. Open `http://127.0.0.1:8080` and chat with the chatbot!

![Conversation with a chatbot on two tabs](https://dev-to-uploads.s3.amazonaws.com/uploads/articles/25pqspqkga6ep1xvkb2p.gif)

You can see that the chatbot continues the conversation (it remembers the previous answers) even when we open a new tab.

What we implemented in this article is briefly described in the Rasa documentation [here](https://rasa.com/docs/rasa/connectors/hangouts/).

Repository for this tutorial:
{% github petr7555/rasa-dev-tutorial no-readme %}

You can checkout the state of the repository at the end of this tutorial by running:
```bash
git clone --branch 24-session-persistence git@github.com:petr7555/rasa-dev-tutorial.git
```