botfront / rasa-webchat

A feature-rich chat widget for Rasa and Botfront
https://botfront.io/rasa
Apache License 2.0
952 stars 496 forks source link

Is there a way to dynamically change socketio URL #188

Closed gourmetseed closed 3 years ago

gourmetseed commented 4 years ago

The use case I'm looking at is something like human handoff. For example, when human is desired a custom action is triggered and following is the payload, {handoff: true, humanURL: "localhost:5006"}. So, when the Widget sees the payload, it disconnect from the Rasa socketio, and connect to the new URL that has been provided in the payload.

This may not be limited to human handoff, one may have multiple agents just to support different part of the domain knowledge.

harveyvandermeer commented 4 years ago

Great idea! I’ve been looking Into changing the socket.io Channel as a solution. Your proposal would be a much cleaner solution Have you found an alternative solution yet? Would it be possible to change the avatar on swapping as well? (And keep the previous avatar in the chat history)

gourmetseed commented 4 years ago

Nope, I haven't found any alternative yet. I could try to work on a solution for this if you don't mind. But it might take some time as I'm not a React person. Current I'm using wrapper to use your component in Vue. Regarding the avatar swapping I think it should be doable. Maybe as a simple solution, we can wrap the new avatar URL inside the Rasa custom action payload.

pengyou200902 commented 4 years ago

Nope, I haven't found any alternative yet. I could try to work on a solution for this if you don't mind. But it might take some time as I'm not a React person. Current I'm using wrapper to use your component in Vue. Regarding the avatar swapping I think it should be doable. Maybe as a simple solution, we can wrap the new avatar URL inside the Rasa custom action payload.

how do you use this rasa-webchat in vue ?

MatthieuJnon commented 4 years ago

Hi, you could listen to the bot_uttered event in the onSocketEvents prop.

When you receive the handoff message, you can then update the socketUrl prop. let me know if you're able to do it

stale[bot] commented 3 years ago

This issue has been automatically marked as stale because it has not had recent activity. It will be closed if no further activity occurs. Thank you for your contributions.

Apatsi commented 2 years ago

Did anyone find a solution how to make a handoff through botfront rasa-webchat?

jusce17 commented 2 years ago

Hi Did anyone find a solution ?

harveyvandermeer commented 2 years ago

Take a look at MatthieuJnon comments on 21 Jul 2020 if you want a client side solution. We however, decided to do this server side and created a 'router' which mimics the socketio traffic and forwards this to the RASA Rest/callback API. Whenever a handoff payload is received, the 'router' forwards all traffic to a live chat solution.

jusce17 commented 2 years ago

Thanks for the reply @harveyvandermeer

Interesting applying this on server side, I am not much of a JS background, but what I have is something like this

        onSocketEvent:{
            'bot_uttered': function(e) {

                if (e.text == <<SPECIFIC_TEST>>){

                    this.socketUrl = <<NEW_URL>>

                }
            },

            },

But this is not changing the socketio URL

jusce17 commented 2 years ago

Also @harveyvandermeer, is this chat widget set to connect to any socket.io server (e.g: FastAPI in python) or additional work must be done ?

harveyvandermeer commented 2 years ago

@jusce17 We haven't put effort in client side solutions. We wanted it server side anyway and not dependent on the channel. Any Socket.io server will do, we used a Sanic server for our solution. Do pay attention to the widget version 1.0.1 / 1.0.0 and the Rasa/botfront server version or your own implementation. There is a breaking change in the socket.io libraries used. If you're working with recent versions you're probably safe. What are you trying to achieve anyway?

jusce17 commented 2 years ago

@harveyvandermeer I am trying to implement the same old problem "The Rasa handoff". my idea is to have the widget on the frontend, and upon a specific message change the socketio URL to a url where the user can talk to a live agent.

Versions
rasa-webchat :1.0.1
rasa : 2.8.26

do you have any tip on how to achieve it ?

TIA

harveyvandermeer commented 2 years ago

@jusce17 Are you trying to implement your own live agent / live chat solution?

jusce17 commented 2 years ago

@harveyvandermeer yes, so basically, I would to redirect the messages to a *middleware who will take care of forwarding(and back) the messages to Salesforce.

Imagine, you are talking to the bot through the widget and you decide to talk to a human, I am looking for a way to dynamically change the url, so that the messages go a flask backed middleware

harveyvandermeer commented 2 years ago

@jusce17 Doesn't Salesforce have a widget and livechat feature which you can integrate with other bots?

DamianPliszczuk commented 2 years ago

Hi @jusce17. Did you manage to solve this issue? Currently, I am also working on transferring the conversation to e.g. a consultant and the best solution would be to do it from the frontend level, as you mentioned. However, I cannot dynamically change the URL address after onSocketEvent (even though I change e.g. the title of the chat window). Regards

jusce17 commented 2 years ago

@harveyvandermeer they have it indeed, for some reason the company want to have another stack on the front end, and salesforce on the back-end only for human-to-human interaction.

@DamianPliszczuk I managed to come up with a workaround which I honestly find it messy and may require additional work, but basically, I wrote the same function twice (there is def a better way to do it)

the first function is wired to a rasa bot, and on a specific message keyword it triggers the second function which is wired to another backend system where humans can text back.

e.g.


<script>

    function handoff () {             
        let e = document.createElement("script"),
            t = document.head || document.getElementsByTagName("head")[0];

            (e.src ="static/index.min.js");  
            (e.async = !0);

            (e.onload = () => {
            window.WebChat.default(
                {
                selector: "#webchat",       
                socketUrl: "http://rasa-url",
                socketPath: "/socket.io/",
                title: "Live Agent",
                subtitle: "ready to help 24/7",
                params: {"storage": "session"},  

                // connect to rasa on command
                onSocketEvent:{
                    'bot_uttered': function(e) {
                        console.log(e.text)
                        if (e.text =="I am  sending you back to RASA BOT"){
                            return rasabot();

                        }

                    },               

                    },

                },

                null
            );
            }),
            t.insertBefore(e, t.firstChild);      

        }

    function rasabot () {      

        let e = document.createElement("script"),
            t = document.head || document.getElementsByTagName("head")[0];

            (e.src ="static/index.min.js");  
            (e.async = !0);

            (e.onload = () => {
            window.WebChat.default(
                {
                selector: "#webchat",
                socketUrl: "http://rasa-url",
                socketPath: "/socket.io/",   
                title: "Rasa Bot",
                subtitle: "ready to help 24/7",
                params: {"storage": "session"},    

                // connect to a human agent on command
                onSocketEvent:{
                    'bot_uttered': function(e) {
                        console.log(e.text)
                        if (e.text =="I am connecting you to a human"){
                            return handoff();

                        }

                    },               

                    },                              

                },

                null
            );
            }),
            t.insertBefore(e, t.firstChild);       

        }
    !(rasabot);

</script>  
</html>