botframeworkweb-chat

How to continue previous conversations with transcript data in Bot Framework and WebChat


Solutions like ChatGPT, Perplexity, and Copilot provide ways for users to reopen older conversations. I am trying to implement a similar feature using the Bot Framework and WebChat.

My setup

Last year I built a RAG-type chatbot for internal use at a company, using Bot Framework and WebChat as the chat interface. The bot is set up to use TranscriptLoggerMiddleware to log conversation activities in Blob storage for quality and review purposes.

My requirements

I want to enable users to view a list of their previous conversations (which is working). When a user selects a conversation, an event triggers a new chat session. This new session should ideally:

Relevant code components I already use Middleware for saving conversation references in table storage

const { ActivityTypes, TurnContext } = require('botbuilder');
const helper = require('../utils/helper');

class ConversationReferenceLoggerMiddleware {
    async onTurn(context, next) {
        if (context.activity.type === ActivityTypes.Message) {
            const conversationReference = TurnContext.getConversationReference(context.activity);
            try {
                await helper.saveConversationReference(conversationReference);
            } catch (error) {
                console.error('Error saving Conversation Reference:', error);
            }
        }
        await next();
    }
}

module.exports = ConversationReferenceLoggerMiddleware;

TranscriptLoggerMiddleware to store conversation history in Blob storage:

const { TranscriptLoggerMiddleware } = require('botbuilder');

What works

What I need help with

The missing piece is figuring out how to take the stored activities from the selected historic conversation and replay them in the new session so that it looks like the user can continue from where they left off.

Most samples I've found are focused on displaying history rather than enabling a seamless continuation of the conversation.

My question

How can I initialize a new WebChat session with a selected conversation’s history so that the user can continue interacting as if it was the original conversation? Any guidance on methods, configuration, or references would be highly appreciated!

[update 14/11]

I installed sample https://github.com/EricDahlvang/BotBuilder-Samples/tree/eric/node_conversationHistory/samples/javascript_nodejs/22.conversation-history Looks promising. Will start with that approach.


Solution

  • If you are using BotFramework-Webchat, then you can pass an array of activities into the store when it is created. The array is placed within the first set of curly brackets.

    Activities array:

    const activities = [
        {
            ...first activity...
        },
        {
            ...second activity...
        },
        ...
    ]
    

    The code normally looks like this:

    const store = window.WebChat.createStore( {}, ( { dispatch } ) => next => async action => {
        next( action)
    });
    

    Now, with the activities array added in:

    const store = window.WebChat.createStore( { activities }, ( { dispatch } ) => next => async action => {
        next( action)
    });
    

    Some things to note:

    1. The activities will display in the transcript window regardless of whether the Web Chat instance initializes correctly or not.
    2. Web Chat is a tiny bit picky about what properties are allowed in the activities contained within the array. Most are alright, but there are two or three it doesn't like (or didn't when last I set this up). Unfortunately, I don't remember which they were. localTimestamp was maybe one...maybe. Anyhow, be prepared to have to sort this out a bit.
    3. If memory serves me right, it also wants a webchat:fallback-text property set within the channelData property. You can experiment with this property's value, if you want. I set mine to an empty string ("").
    4. Not a 100% on this, but I believe each activity in the array needs to be in JSON format. So, properties and values need to be wrapped in double quotes, except number and boolean values.
    5. The last activity (activities, if several were sent together), which likely will have come from the bot, will assume the time stamp of the next new/incoming activity which is also likely coming from the bot. In other words, if the last posted message ('Thank you for visiting') was from the bot sent on 'December 1 at 12:02 PM' and the next posted message ('How can I help?') is from the bot sent on 'December 9 at 8:39 AM', Web Chat will group these together using the 'December 9' date. The only way to get around this (if that is your wish) is to pass in the groupTimestamp property into styleOptions and assign it a number value representing milliseconds. For instance, groupTimestamp: 300 will group all activities together that are within 300 ms of each other.
    6. Because we are injecting the past conversational transcript via the activities array into Web Chat, the activities will not pass thru the DirectLine connector and, subsequently, to your bot. Any event or activity that is contained within the activities array that otherwise would have initiated a certain response in your bot will not occur in this instance. The passed in activities array is purely for display purposes only.

    As you can see in the below clip, all the dialog prior to the 'User joined conversation' comment from the bot is coming from the passed in activities array. Each prior activity has a June timestamp and the newer with a December timestamp. As mentioned above, I have set groupTimestamp to 300 so older activities are grouped together by older dates, and newer by newer dates.

    Preloaded Activities in Web Chat

    Hope of help!