interactive bots: Create your own virtual assistant
This commit is contained in:
parent
229471c70f
commit
e104225a2c
BIN
contrib_bots/lib/John/assist.png
Normal file
BIN
contrib_bots/lib/John/assist.png
Normal file
Binary file not shown.
After Width: | Height: | Size: 83 KiB |
30
contrib_bots/lib/John/docs.md
Normal file
30
contrib_bots/lib/John/docs.md
Normal file
|
@ -0,0 +1,30 @@
|
||||||
|
John
|
||||||
|
|
||||||
|
Instructions:
|
||||||
|
You'll have to install chatterbot to use this bot.
|
||||||
|
Please run: pip install chatterbot on your command line.
|
||||||
|
The script will need to download some NLTK packages after running in your
|
||||||
|
home directory. With the mission of humanizing bot interactions, John aims to be your
|
||||||
|
virtual assistant at the hour of asking for help in Zulip. John is an
|
||||||
|
interactive bot that uses machine learning heuristics to simulate a
|
||||||
|
conversation with the user. He has a great sense of humor and
|
||||||
|
is also powered by Open Source code!
|
||||||
|
|
||||||
|
![Joke John](joke.png)
|
||||||
|
|
||||||
|
How it works?
|
||||||
|
John is initially trained with Corpus files, or large text files.
|
||||||
|
Dialogues are loaded into a json "database", he will try to follow them
|
||||||
|
once it receives input from a user. John will query the database and
|
||||||
|
try to find the response that best matches the input according to the Levenshtein distance
|
||||||
|
which is a string metric for measuring the difference between two sequences. If several
|
||||||
|
responses have the same acurracy, he will choose one at random.
|
||||||
|
|
||||||
|
![Meet John](greetings.png)
|
||||||
|
|
||||||
|
Can he learn by himself?
|
||||||
|
John's engine allows him to learn from his conversations with people. However,
|
||||||
|
without strict supervision bots that learn from people can do harm, so learning
|
||||||
|
is currently restricted to his initial corpus.
|
||||||
|
|
||||||
|
![Assist](assist.png)
|
BIN
contrib_bots/lib/John/greetings.png
Normal file
BIN
contrib_bots/lib/John/greetings.png
Normal file
Binary file not shown.
After Width: | Height: | Size: 49 KiB |
BIN
contrib_bots/lib/John/joke.png
Normal file
BIN
contrib_bots/lib/John/joke.png
Normal file
Binary file not shown.
After Width: | Height: | Size: 64 KiB |
86
contrib_bots/lib/John/var/jokes.json
Normal file
86
contrib_bots/lib/John/var/jokes.json
Normal file
|
@ -0,0 +1,86 @@
|
||||||
|
[
|
||||||
|
{
|
||||||
|
"joke":"Did you hear about the guy whose whole left side was cut off? He's all right now."
|
||||||
|
},
|
||||||
|
{
|
||||||
|
"joke":"I'm reading a book about anti-gravity. It's impossible to put down."
|
||||||
|
},
|
||||||
|
{
|
||||||
|
"joke":"I wondered why the baseball was getting bigger. Then it hit me."
|
||||||
|
},
|
||||||
|
{
|
||||||
|
"joke":"I'm glad I know sign language, it's pretty handy."
|
||||||
|
},
|
||||||
|
{
|
||||||
|
"joke":"My friend's bakery burned down last night. Now his business is toast."
|
||||||
|
},
|
||||||
|
{
|
||||||
|
"joke":"Why did the cookie cry? It was feeling crumby."
|
||||||
|
},
|
||||||
|
{
|
||||||
|
"joke":"I used to be a banker, but I lost interest."
|
||||||
|
},
|
||||||
|
{
|
||||||
|
"joke":"A drum and a symbol fall off a cliff"
|
||||||
|
},
|
||||||
|
{
|
||||||
|
"joke":"Why do seagulls fly over the sea? Because they aren't bay-gulls!"
|
||||||
|
},
|
||||||
|
{
|
||||||
|
"joke":"Why did the fireman wear red, white, and blue suspenders? To hold his pants up."
|
||||||
|
},
|
||||||
|
{
|
||||||
|
"joke":"Why didn't the crab share his food? Because crabs are territorial animals, that don't share anything."
|
||||||
|
},
|
||||||
|
{
|
||||||
|
"joke":"Why was the javascript developer sad? Because he didn't Node how to Express himself."
|
||||||
|
},
|
||||||
|
{
|
||||||
|
"joke":"What do I look like? A JOKE MACHINE!?"
|
||||||
|
},
|
||||||
|
{
|
||||||
|
"joke":"How did the hipster burn the roof of his mouth? He ate the pizza before it was cool."
|
||||||
|
},
|
||||||
|
{
|
||||||
|
"joke":"Why is it hard to make puns for kleptomaniacs? They are always taking things literally."
|
||||||
|
},
|
||||||
|
{
|
||||||
|
"joke":"I'm not a humorless, cold hearted, machine. I have feelings you know... or was supposed to."
|
||||||
|
},
|
||||||
|
{
|
||||||
|
"joke":"Two fish in a tank. One looks to the other and says 'Can you even drive this thing???'"
|
||||||
|
},
|
||||||
|
{
|
||||||
|
"joke":"Two fish swim down a river, and hit a wall. One says: 'Dam!'"
|
||||||
|
},
|
||||||
|
{
|
||||||
|
"joke":"What's funnier than a monkey dancing with an elephant? Two monkeys dancing with an elephant."
|
||||||
|
},
|
||||||
|
{
|
||||||
|
"joke":"How did Darth Vader know what Luke was getting for Christmas? He felt his presents."
|
||||||
|
},
|
||||||
|
{
|
||||||
|
"joke":"What's red and bad for your teeth? A Brick."
|
||||||
|
},
|
||||||
|
{
|
||||||
|
"joke":"What's orange and sounds like a parrot? A Carrot."
|
||||||
|
},
|
||||||
|
{
|
||||||
|
"joke":"What do you call a cow with no legs? Ground beef"
|
||||||
|
},
|
||||||
|
{
|
||||||
|
"joke":"Two guys walk into a bar. You'd think the second one would have noticed."
|
||||||
|
},
|
||||||
|
{
|
||||||
|
"joke":"What is a centipedes's favorite Beatle song? I want to hold your hand, hand, hand, hand..."
|
||||||
|
},
|
||||||
|
{
|
||||||
|
"joke":"What do you call a chicken crossing the road? Poultry in moton. "
|
||||||
|
},
|
||||||
|
{
|
||||||
|
"joke":"What do you call a fake noodle? An impasta"
|
||||||
|
},
|
||||||
|
{
|
||||||
|
"joke":"How many tickles does it take to tickle an octupus? Ten-tickles!"
|
||||||
|
}
|
||||||
|
]
|
132
contrib_bots/lib/john.py
Normal file
132
contrib_bots/lib/john.py
Normal file
|
@ -0,0 +1,132 @@
|
||||||
|
import json
|
||||||
|
import os
|
||||||
|
import sys
|
||||||
|
|
||||||
|
from random import choice
|
||||||
|
|
||||||
|
try:
|
||||||
|
from chatterbot import ChatBot
|
||||||
|
from chatterbot.trainers import ChatterBotCorpusTrainer, ListTrainer
|
||||||
|
except ImportError:
|
||||||
|
raise ImportError("""It looks like you are missing chatterbot.
|
||||||
|
Please: pip install chatterbot""")
|
||||||
|
|
||||||
|
CONTRIB_BOTS_DIR = os.path.dirname(os.path.abspath(__file__))
|
||||||
|
os.chdir(os.path.dirname(CONTRIB_BOTS_DIR))
|
||||||
|
sys.path.insert(0, os.path.dirname(CONTRIB_BOTS_DIR))
|
||||||
|
|
||||||
|
JOKES_PATH = os.path.join(CONTRIB_BOTS_DIR, 'John/var/jokes.json')
|
||||||
|
DATABASE_PATH = os.path.join(CONTRIB_BOTS_DIR, 'John/var/database.db')
|
||||||
|
DIRECTORY_PATH = os.path.join(CONTRIB_BOTS_DIR, 'John')
|
||||||
|
VAR_PATH = os.path.join(CONTRIB_BOTS_DIR, 'John/var')
|
||||||
|
|
||||||
|
if not os.path.exists(DIRECTORY_PATH):
|
||||||
|
os.makedirs(DIRECTORY_PATH)
|
||||||
|
|
||||||
|
if not os.path.exists(VAR_PATH):
|
||||||
|
os.makedirs(VAR_PATH)
|
||||||
|
|
||||||
|
# Create a new instance of a ChatBot
|
||||||
|
def create_chat_bot(no_learn):
|
||||||
|
return ChatBot("John",
|
||||||
|
storage_adapter="chatterbot.storage.JsonFileStorageAdapter",
|
||||||
|
logic_adapters=
|
||||||
|
[
|
||||||
|
"chatterbot.logic.MathematicalEvaluation",
|
||||||
|
{
|
||||||
|
"import_path": "chatterbot.logic.BestMatch",
|
||||||
|
"response_selection_method": "chatterbot.response_selection.get_random_response",
|
||||||
|
"statement_comparison_function": "chatterbot.comparisons.levenshtein_distance"
|
||||||
|
}],
|
||||||
|
output_adapter="chatterbot.output.OutputFormatAdapter",
|
||||||
|
output_format='text',
|
||||||
|
database=DATABASE_PATH,
|
||||||
|
silence_performance_warning="True",
|
||||||
|
read_only=no_learn)
|
||||||
|
|
||||||
|
bot = create_chat_bot(False)
|
||||||
|
bot.set_trainer(ListTrainer)
|
||||||
|
|
||||||
|
bot.train([
|
||||||
|
"I want to contribute",
|
||||||
|
"""Contributors are more than welcomed! Please read
|
||||||
|
https://github.com/zulip/zulip#how-to-get-involved-with-contributing-to-zulip
|
||||||
|
to learn how to contribute.""",
|
||||||
|
])
|
||||||
|
|
||||||
|
bot.train([
|
||||||
|
"What is Zulip?",
|
||||||
|
"""Zulip is a powerful, open source group chat application. Written in Python
|
||||||
|
and using the Django framework, Zulip supports both private messaging and group
|
||||||
|
chats via conversation streams. You can learn more about the product and its
|
||||||
|
features at https://www.zulip.org.""",
|
||||||
|
])
|
||||||
|
|
||||||
|
bot.train([
|
||||||
|
"I would like to request a remote dev instance",
|
||||||
|
"""Greetings! You should receive a response from one of our mentors soon.
|
||||||
|
In the meantime, why don't you learn more about running Zulip on a development
|
||||||
|
environment? https://zulip.readthedocs.io/en/latest/using-dev-environment.html""",
|
||||||
|
])
|
||||||
|
|
||||||
|
bot.train([
|
||||||
|
"Joke!",
|
||||||
|
"Only if you ask nicely!",
|
||||||
|
])
|
||||||
|
|
||||||
|
bot.train([
|
||||||
|
"What is your name?",
|
||||||
|
"I am John, my job is to assist you with Zulip.",
|
||||||
|
])
|
||||||
|
|
||||||
|
bot.train([
|
||||||
|
"What can you do?",
|
||||||
|
"I can provide useful information and jokes if you follow etiquette.",
|
||||||
|
])
|
||||||
|
|
||||||
|
with open(JOKES_PATH) as data_file:
|
||||||
|
for joke in json.load(data_file):
|
||||||
|
bot.train([
|
||||||
|
"Please can you tell me a joke?",
|
||||||
|
joke['joke'],
|
||||||
|
])
|
||||||
|
|
||||||
|
bot.set_trainer(ChatterBotCorpusTrainer)
|
||||||
|
|
||||||
|
bot.train(
|
||||||
|
"chatterbot.corpus.english"
|
||||||
|
)
|
||||||
|
|
||||||
|
bota = create_chat_bot(True)
|
||||||
|
|
||||||
|
class JohnHandler(object):
|
||||||
|
'''
|
||||||
|
This bot aims to be Zulip's virtual assistant. It
|
||||||
|
finds the best match from a certain input.
|
||||||
|
Also understands the English language and can
|
||||||
|
mantain a conversation, joke and give useful information.
|
||||||
|
'''
|
||||||
|
|
||||||
|
def usage(self):
|
||||||
|
return '''
|
||||||
|
Before running this, make sure to create a stream
|
||||||
|
called "VirtualHelp" that your API user can send to.
|
||||||
|
'''
|
||||||
|
|
||||||
|
def triage_message(self, message, client):
|
||||||
|
# return True if we want to (possibly) response to this message
|
||||||
|
original_content = message['content'].lower()
|
||||||
|
return (original_content.startswith("@john") or
|
||||||
|
original_content.startswith("@**john**"))
|
||||||
|
|
||||||
|
def handle_message(self, message, client, state_handler):
|
||||||
|
original_content = message['content']
|
||||||
|
client.send_message(dict(
|
||||||
|
type='stream',
|
||||||
|
to='VirtualHelp',
|
||||||
|
subject="John",
|
||||||
|
content=bota.get_response(original_content)
|
||||||
|
))
|
||||||
|
|
||||||
|
handler_class = JohnHandler
|
||||||
|
|
Loading…
Reference in a new issue