The Python chatbot framework with batteries included
Project description
The Python chatbot framework with batteries included
If you've ever developed a chatbot or otherwise virtual assistant
-how many times have you had to iterate over the message contents to route the message to the correct part of your code? Or even worse; How many hours have you spent on trying to decipher a message and its contents to find words of interest? Maybe the name of a song, or a phone number? Or a username?
I had enough of that - so I wrote this framework.
The Pyttman Framework aims to provide a similar experience as Django and Flask does for web, but for chatbots and digital assistants. It's large and full of features yet easy to use.
Ability, Intent, Entity
Pyttman apps are structured with inspiration from the MVC (Model View Controller) pattern, but things are named a bit differently. Here's a short rundown on what they're about.
Ability
Chatbots can have many areas of capabilities; Anything from answering questions, searching the web,
playing songs to playing games. I call these Abilities, which encapsulate responses to
queries in the same domain. The Ability class has Intent
classes, and acts like a hub for the Intent classes which
correspond to the same domain of the application. The ability to store expenses may contain
many components - saving new expenses, visualizing existing ones, searching for records, etcetera.
Ability classes also facilitate a session storage object accessible in the Ability as self.storage
and in intent classes
as self.ability.storage
. This allows efficient and safe memory storage for intents to manipulate data in their respective
domain, without global variables and risking exposing data to intents of another domain.
class MusicPlayer(Ability):
"""
This Ability class holds Intent classes which serve users
ways to play music through the chatbot.
"""
# Intent classes are added to this tuple for them to be available
# to users when the application starts.
intents = (PlaySong,
RepeatSong,
FindSongByLyrics)
Intent
The Intent class is the heart of the Pyttman development experience. They are classes, 1:1 to a message and a response.
If you're a web developer, you see the similarity to a controller.
Here, we tell which messages it should match and also how to respond with
implementing the respond
method.
Consider a message like Play Last Train Home by John Mayer on Spotify
.
class PlaySong(Intent):
"""
Lets people play songs on either YouTube, Spotify or SoundCloud.
"""
lead = ("play",)
exclude = ("on",) # These words will be excluded in all entities.
song = TextEntityField(span=5)
artist = TextEntityField(prefixes=("by", "with"), span=10)
shuffle_songs = BoolEntityField(message_contains=("shuffle",))
platform = TextEntityField(as_list=True, valid_strings=(
"Spotify", "SoundCloud", "YouTube")
)
def respond(self, message: Message) -> Reply | ReplyStream:
song = message.entities["song"]
artist = message.entities["artist"]
shuffle_songs = message.entities["shuffle_songs"]
platform = message.entities["platform"]
# Play the song...
return Reply(f"Playing {song} by {artist} on {platform}!")
Entity
What are those EntityField
classes in the example above?
In Pyttman, the Entity is a word, or several words sought in a message. When writing chatbots it's very common to have to parse the message from humans to try and find words of interest. Maybe your chatbot registers purchases in a database. You'll need to parse the name of the purchased item as well as the price. But how do you know where to stop the name of the item? It could be one word, or several. The price could be mentioned first - or last - or in the middle of the message. Positioning won't help. Regex? This repetitive and complex process also won't scale. When you've invented the parser for one answer, you'll need to do it again for the next thing your chatbot can do.
Let's take a closer look at the example code above.
This EntityField declared in the Intent class above tells Pyttman that you're looking for
a text value in the message. The span
argument defaults to 1, but in this case is set to 5.
That means the value parsed here can be 5 words long, at the longest - after which Pyttman will
stop adding words to the entity, should it be any longer than that.
song = TextEntityField(span=5)
This EntityField is convenient for flags; it will set itself to True
if a matching word was found in the message, otherwise False
.
shuffle_songs = BoolEntityField(message_contains=("shuffle",))
For situations where a set of known valid choices are available, the valid_strings
argument can be provided, rendering all other words ignored.
In the example below, message.entities["platform"]
can only ever be Spotify, SoundCloud, YouTube
or its default
which defaults to None
.
platform = TextEntityField(as_list=True, valid_strings=(
"Spotify", "SoundCloud", "YouTube"))
When the message has entered the respond
method of the matching Intent, the entities are
available on the entities
property on the Message
object.
Given the Intent above and the message Play Last Train Home by John Mayer on Spotify
, the dictionary message.entities
look like this:
{
'song': 'Last Train Home',
'artist': 'John Mayer',
'shuffle_songs': False,
'platform': 'Spotify'
}
Easy to get started with
Pyttman ships with a CLI tool which is available after pip install. It helps creating and running your apps with simple commands.
# Install it
pip install pyttman
# Create an app from a template
pyttman new app my_first_app
# Create an Ability module with files from a template
pyttman new ability ability_name my_first_app
# Run it in dev mode
pyttman dev my_first_app
# Run it in shell mode, and interact with your objects through a console with Pyttman
modules and objects loaded
pyttman shell my_first_app
# Run it in production mode, for your platform of choice as set in settings.py
pyttman runclient my_first_app
Discord support built in - No extra code to get your chatbot online
Pyttman aims to offer developers a platform-independent experience. We're constantly developing support for more platforms. As of today, Pyttman offers built-in support for Discord through the discord.py library, and we have more on the way. All you have to do is to do is choose which platform client you use in settings.py for your app to go online on a different platform.
The TL:DR
- App creation and orchestration using a built-in CLI tool:
pyttman <subcommand> <args>
- Class-based Intents -> similar to APIView classes, to match patterns of words (rules) to your code. Ability classes wrap around Intents, which provides encapsulation and offers lifecycle hooks.
- Built-in help generators for end-users based on metadata in your Intents
- Built-in support for Discord - more platforms to come.
- Encapsulated storage objects accessible within Intents, scoped under Ability classes
- Built-in thread based task scheduler
- Abstraction layer middleware for managing incoming Messages just like requests in API frameworks
- Django-like settings.py file
- Powerful built-in rule-based API for parsing entities in messages (identifying words based on pre/suffixes and/or regex patterns, and/or order of appearance
Documentation
Check out the Pyttman Wiki for documentation and tutorials.
Community
Join the Pyttman Discord! We're a small but growing community of developers and enthusiasts.
Contributions
We're looking for more contributors! Contribute with code in a PR or join our community to share ideas and thoughts.
Open source notices
Thank you to all developers who worked on the following dependencies:
- Pyttman uses Py7zr for extractions
- Pyttman uses MultiDict in its scheduler API
- Pyttman uses pytz for timezones
- Pyttman uses requests in tools offering easier API integration
- Pyttman uses discord.py when adding support for native development of apps integrated with the Discord platform. discord.Client and discord.Message are subclassed.
Project details
Release history Release notifications | RSS feed
Download files
Download the file for your platform. If you're not sure which to choose, learn more about installing packages.
Source Distribution
Built Distribution
File details
Details for the file Pyttman-1.3.2.tar.gz
.
File metadata
- Download URL: Pyttman-1.3.2.tar.gz
- Upload date:
- Size: 60.9 kB
- Tags: Source
- Uploaded using Trusted Publishing? No
- Uploaded via: twine/4.0.2 CPython/3.11.3
File hashes
Algorithm | Hash digest | |
---|---|---|
SHA256 | 74341993cd16425a27d5c7a454588d92573edde5224540b1d12c03887e8f3ccf |
|
MD5 | cb88f196cfd38114ecf4e7dcd530577f |
|
BLAKE2b-256 | f26ed99cba9bdc9d1089fc915690499ca0ee6df655dfd6898099697711600403 |
File details
Details for the file Pyttman-1.3.2-py3-none-any.whl
.
File metadata
- Download URL: Pyttman-1.3.2-py3-none-any.whl
- Upload date:
- Size: 75.6 kB
- Tags: Python 3
- Uploaded using Trusted Publishing? No
- Uploaded via: twine/4.0.2 CPython/3.11.3
File hashes
Algorithm | Hash digest | |
---|---|---|
SHA256 | 0c5d9a3e0e342a608834b2bb530a7f77dea716b0ef55d0895c028b94b9a8136d |
|
MD5 | b7d9dc833b5ac8f148390065ca8a1dfe |
|
BLAKE2b-256 | 2202a18bcd54d25b5f245c6e2c7fb537db1db854886065cd7b61a9f35f21f51e |