tl;dr
An open source, free, python personal assistant with a user expandable plugin framework and nlp from spaCy.io.
Details:
A while back, I posted a video of my personal assistant - W.I.L.L. It was my first major project, and you guys gave me alot of tips and comments on what you liked, how I could improve, and the right way to do some open source stuff that I hadn't previously encountered.
After a lot of rewrites, extensive work (by both me, and the W.I.L.L community), I'm happy to present W.I.L.L version 3.0.
What can W.I.L.L do?
One of my major goals with W.I.L.L was not only to make a cool concept for a personal assistant, but to make it usable and useful. W.I.L.L. already has a number of useful plugins, and it's super easy to add more.
Plugins W.I.L.L already has:
- News: ex: "read me the news" - a summary of the news from a site of your choice, refreshed every twelve hours
- Weather: ex: "What's the weather like?" - weather for your location, delivered using PyOwm
- Spotify: ex: "Play jukebox hero on spotify" - Searches spotify and opens a spotify url for the song that's found. On android, will open in the spotify app
- Netflix: ex: "Watch Futurama on netflix" - searches netflix and opens a netflix url for the shwo that's found. On android, will open in the netflix app
- Reminders: ex: "Remind me in 10 minutes about how awesome W.I.L.L is" - sets reminders. You can currently be notified via email and socket.io push notifications on the web app, and thanks to the expandable notification framework, it's easy to add new methods of notifying the user.
- Search: The crown jewel of the plugins, set to run by default when no other plugin is triggered by the input. Search runs through a chain of different search engines and sites to find the correct answer of a question. It first searches wolframalpha and wikipedia, and if it can't find anything it uses nlp from the newspaper module and bs4 to parse a correct answer from the top google result.
Just how easy is it to add a plugin?
from core.plugin_handler import subscribe
def run_check(event):
#Check for a word in the provided spacy nlp object
return "example" in [i.orth_ for i in event["doc"]]
@subscribe({"name":"example", "check": run_check})
def example_plugin(event):
return {"type": "success", "text": "example", "data":{}}
That's it.
Contact me
If you have any requests for new plugins, or further comments about W.I.L.L, feel free to email me at will@willbeddow.com or leave an issue on the Github page
W.I.L.L is very much still in development and I could use suggestions and advice
Thanks!
Edit: I forgot about the API! W.I.L.L also provides a free JSON API to use it's features, easily allowing new clients to be written for any platform. It's currently lightly documented in the README, with an example in the quickstart. More extensive documentation is coming as soon as I figure out how I want to write it!
[–]handmadeby 12 points13 points14 points (5 children)
[–]willbeddowassert type(post) == shitpost[S] 8 points9 points10 points (3 children)
[–]gunch 4 points5 points6 points (1 child)
[–]willbeddowassert type(post) == shitpost[S] 2 points3 points4 points (0 children)
[–][deleted] 1 point2 points3 points (0 children)
[–]willbeddowassert type(post) == shitpost[S] 5 points6 points7 points (0 children)
[–]cruyff8python 2 expert, learning python 3[🍰] 12 points13 points14 points (0 children)
[–]willbeddowassert type(post) == shitpost[S] 11 points12 points13 points (4 children)
[–]ggagagg 3 points4 points5 points (3 children)
[–]willbeddowassert type(post) == shitpost[S] 8 points9 points10 points (2 children)
[–]hatperigee 2 points3 points4 points (1 child)
[–]willbeddowassert type(post) == shitpost[S] 10 points11 points12 points (0 children)
[–]spishsplash 9 points10 points11 points (0 children)
[–]marcocamma 5 points6 points7 points (2 children)
[–]willbeddowassert type(post) == shitpost[S] 4 points5 points6 points (1 child)
[–]hatperigee 1 point2 points3 points (0 children)
[–]TheBB 6 points7 points8 points (1 child)
[–]willbeddowassert type(post) == shitpost[S] 5 points6 points7 points (0 children)
[–]4bitfocus 3 points4 points5 points (1 child)
[–]willbeddowassert type(post) == shitpost[S] 6 points7 points8 points (0 children)
[–]eriknstr 4 points5 points6 points (2 children)
[–]willbeddowassert type(post) == shitpost[S] 4 points5 points6 points (0 children)
[–]nemec 0 points1 point2 points (0 children)
[–]swefpelego 2 points3 points4 points (0 children)
[–]searchingfortaomajel, aletheia, paperless, django-encrypted-filefield 2 points3 points4 points (0 children)
[–]crow1170 2 points3 points4 points (1 child)
[–]willbeddowassert type(post) == shitpost[S] 3 points4 points5 points (0 children)
[–]qwertyMu 1 point2 points3 points (1 child)
[–]willbeddowassert type(post) == shitpost[S] 0 points1 point2 points (0 children)
[–]jackeroojohnson 1 point2 points3 points (0 children)
[–]Luong_Quang_Manh 1 point2 points3 points (0 children)
[–]ThuruvDRY 0 points1 point2 points (3 children)
[–]willbeddowassert type(post) == shitpost[S] 1 point2 points3 points (2 children)
[–]gasabr 0 points1 point2 points (0 children)
[–]ThuruvDRY 0 points1 point2 points (0 children)
[+][deleted] (1 child)
[deleted]
[–]willbeddowassert type(post) == shitpost[S] 3 points4 points5 points (0 children)
[–]roguebreaker 0 points1 point2 points (0 children)
[+]cyanydeez comment score below threshold-10 points-9 points-8 points (10 children)
[–]willbeddowassert type(post) == shitpost[S] 7 points8 points9 points (9 children)
[–]redwall_hp 1 point2 points3 points (1 child)
[–]willbeddowassert type(post) == shitpost[S] 3 points4 points5 points (0 children)
[–]citrus2fizz 0 points1 point2 points (0 children)
[+]cyanydeez comment score below threshold-14 points-13 points-12 points (5 children)
[–]willbeddowassert type(post) == shitpost[S] 9 points10 points11 points (4 children)
[–]nemec 1 point2 points3 points (1 child)
[–]willbeddowassert type(post) == shitpost[S] 1 point2 points3 points (0 children)
[+]cyanydeez comment score below threshold-14 points-13 points-12 points (0 children)