-
Notifications
You must be signed in to change notification settings - Fork 103
New issue
Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.
By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.
Already on GitHub? Sign in to your account
How to implement conversation? #140
Comments
How long do you need the state to be retained? I did some state stuff by just keeping the state in memory, if the bot restarts the state is lost, but for my needs that was fine. The second way I added state retention is by adding a db backend for one of the plugins. In my case I use MySQL, but you can do whatever you want. The bot is in python, so there are plenty of options out there for you to store your state :) |
I didn't go so much into the technical bits back there. On my local setup I also have a SQLite/SQLAlchemy db. This could indeed be used for the state and could even be made to persist across reboots. What I'm not sure about is how to implement the back and forth communication. If you check my example above, the replies by I'm also thinking that this kind of stateful interaction could be made to work through any communication channel but is probably easier to use via private message where you don't need to |
Yes totally understand this conundrum. In my instance, the best solution I came up with was forcing this type of conversation to happen only as a direct message between the bot and the person. I have not played with the choice stuff much, but I do believe there is some support for displaying a modal with buttons that can correspond to actions. Similar to how some plugins do it. I am pretty sure the API supports it, but I don't think mmpy_bot has everything needed for that. |
Thanks for the feedback Alex. Would it be possible for you to share some of the code or the design of the approach you used in your instance? The only directions I'm seeing right now involve some hacky changes to mmpy_bot's core or some significant ones that would affect the interface between plugins and the messaging classes. Too early to say but some may be backwards incompatible. |
Sure, so I used it for onboarding new users. Here is the function used to start the onboarding: @respond_to('start foobar onboarding')
def foobar_start_onboarding(message):
""" ***Direct Message Only!*** Start the **one time** process of getting authenticated"""
if not message.is_direct_message():
message.reply("I am sorry for security reasons you must start the onboarding process from a Direct Message.")
return
message.send("Visit the [FooBar Token](https://foobar.example.com/) page to create a new foobar token or get an existing token ")
message.send("If you need help with creating the token take a look at the instructions located [here](https://foobar.example.com/token_help)")
message.send("According to IT it should take around 10 minutes for the token to become active, so wait 10 minutes after you get the token")
message.send("Once you have the token and have waited 10 minutes let me know what it is by saying `my foobar token is <your_token>`") And here is a function used to check if the user has already gone through the onboarding process. The def foobar_onboarding_done(message):
""" Check to make sure the onboarding process for FOOBAR is complete and return token """
if not api_keys.has_key(message.get_user_mail(),"foobar"):
message.reply("this appears to be the first time you have tried to use me to interact with FOOBAR. Please start a Direct Message with me and type `start foobar onboarding`")
return False
return True And here is the function I use to finish the onboarding process: @respond_to('my foobar token is (.*)')
def foobar_finish_onboarding(message, token):
""" ***Direct Message Only!*** Provide a token to use when interacting with FOOBAR"""
if not message.is_direct_message():
message.reply("I am sorry for security reasons you must use Direct Message when providing your FOOBAR Token.")
return
if len(token) > 64:
message.send("The token you sent, seems too long to be valid, please try again")
return
# Check to make sure the token works
message.send("Hold on, checking your token, this should not take long ....")
id = foobar_get_widget_by_name(message.get_username(), token)
if id != "8675309":
message.send("I was not able to use your token to interact with FOOBAR. Please report this in ~support")
# Store token for Future use
api_keys.add_key(message.get_user_mail(),"foobar", token)
message.send("All done, token stored succesfully. I should be able to get FOOBAR information for you now.") So then during normal interaction with the bot where it is asked to do things with FOOBAR, all I do is check to make sure the user has been onboarded in the past by adding this check in the respond function: if not foobar_onboarding_done(message):
return resp That is about it, obviously, I redacted this a bit but you should be able to get the idea of what I did. Let me know if you have any questions. |
Hi Alex, thanks a lot for the code examples. I'll explore what changes I'll have to do to mmpy_bot core for this and get back to you. I'll keep any changes in my fork and we can see how/if to integrate them later. |
Hi @unode, did you find a way how to implement a conversation using Thanks, |
Hi @sadok-f not yet. Time constraints... Cheers |
With the refactor in #153, perhaps a nice way to do this would be to register listeners on the fly (currently not supported, but should not be a huge change). You'd have some function with |
@unode Did you ever get what you needed with 2.x on this request? |
@attzonko I haven't been able to experiment with it yet. |
Just giving a brief update here. I don't yet have an implementation that is solid enough to upstream but my latest approach, that is hacky but somewhat functional, is to use Mattermost threads as "state" of conversations. By using threads, the bot can then work stateless and retrieve the full context by requesting the full history of the thread to mattermost. To better support this use-case we would need to have a way to register that replies to a given thread are to be handled by a specific function. I explored two possibilities:
The first works well for pre-defined interaction workflows such as the one described in the opening message of this issue. However the dialog interaction doesn't scale to human-like text interactions that are now possible via large language models (LLM). See below an example interaction. Assume
behind the scenes indicated by
An optional "end of conversation" message can be implemented to delete the thread reference from mmpy_bot. So in short, the hacky part is the need to hide the thread based dispatch logic in This implementation also suffers from some context problems. |
I would like to create some "conversational" plugins.
The core feature currently missing is some form of persistence of state between messages as well as an alternative message routing path for when conversational mode is enabled.
A simple example:
Has anyone implemented anything of this sort?
I have some ideas on how state could be implemented but the tricky part seems to be the conversation.
Does anyone have suggestions of core features that could make this easier/possible?
The text was updated successfully, but these errors were encountered: