De Blogpost Generator

19 maart 2019  |  
7 min leestijd

Sinds ik afgestudeerd ben is mijn leven een stuk drukker geworden. Ik werk 40 uur per week, ben bezig met het voorbereiden van een presentatie voor de Luminis DevCon, ben eindelijk begonnen aan rijlessen en sport ik zelfs twee keer per week. Ik moet nog steeds een beetje wennen aan al die drukte en nu mag ik ook nog een blog schrijven.

Door al die drukte kom ik nooit meer aan het spelen van Super Smash Bros. Ultimate en Beat Saber toe. Het zou daarom mooi zijn als deze blogpost geschreven kan worden door een computer, want dan bespaar ik wat tijd. Gelukkig is dat mogelijk!

Markov Chains

Alleen moet ik er wel zelf voor zorgen dat de computer een blog schrijft, dus het relaxen stel ik nog even uit. Maar als ik ooit weer een blogpost mag schrijven bespaar ik tenminste tijd, dus dat is een mooi vooruitzicht. Om de tekst voor mijn blogpost te genereren ga ik gebruik maken van Python en een Markov Chain. En nee, “Markov Chain” is niet een naam van een rapper.

Wat is een Markov Chain?

Bij een Markov Chain draait het om probabilisme, dat volgens Wikipedia de leer van waarschijnlijkheid is. Dit concept is uit te leggen door middel van veel wiskundige formules, maar met mijn 4,5 voor wiskunde op de middelbare school ga ik daar niet aan beginnen.

Iets makkelijker uitgelegd wordt bij een Markov Chain gebruik gemaakt van staten, één staat kan naar één of meer andere staten of eventueel terug naar zichzelf leiden. De vorige staat/staten hebben geen invloed op de keuze van de volgende staat, want een Markov Chain onthoudt niets. Een Markov Chain is zich alleen bewust van de huidige staat, de staten waar naartoe geleid kan worden en hoe groot de kans is dat naar een specifieke andere staat geleid wordt.
Laat ik dit principe illustreren met een voorbeeld, aangezien er tekst gegenereerd gaat worden neem ik ook tekst als voorbeeld.

Voor een Markov Chain is data nodig, laten we bijvoorbeeld de volgende zinnen als trainingsdata gebruiken:

  • Ik wil geld
  • Ik heb werk
  • Mijn zus wil werk
  • De overheid wil geld

In het geval van tekst is ieder woord een staat. Met dit gegeven in het achterhoofd is het misschien al mogelijk om de relatie tussen de woorden te zien. Laten we als voorbeeld nemen dat een Markov Chain met de staat “ik” begint:

In de trainingsdata leidt “ik” naar wil of heb, wat een kans van 0.5 oplevert. “Heb” leidt altijd naar “werk”, oftewel een kans van 1. “Wil” leidt in twee gevallen naar “geld” en in een geval naar “werk”, oftewel een kans van respectievelijk 0.66(6666) en 0.33.

Als de Markov Chain vervolgens met de staat “de” begint is er minder variatie:

Het is dus belangrijk om veel trainingsdata te verzamelen, zodat het Markov Chain Model zoveel mogelijk variatie krijgt.

Een Markov Chain Toepassen

Als trainingsdata ga ik andere blogs van Luminis gebruiken. Ik heb snel met Node.js een web scraper in elkaar gezet die voor mij de tekst van de blogs ophaalt. Deze tekst wordt vervolgens, na wat herformatteren, in een tekst bestand gezet.

Uiteindelijk houd ik 5984 regels aan Engelstalige blogposts en 925 regels aan Nederlandse blogposts over. Het liefst heb ik meer Nederlandse trainingsdata, maar ik wil ook graag gamen, dus voor nu laat ik het zo.
Voor zowel de Engels als Nederlands teksten ga ik een Markov Chain model maken.

Ik ga Python gebruiken voor het maken van de Markov Chain modellen, hiervoor ga ik de Markovify library gebruiken. Dit is een simpele library, ik voer een verkregen tekstbestand in en daarmee wordt vervolgens een Markov Chain model gemaakt. De code voor het Nederlandse model ziet er als volgt uit:

Zo makkelijk kan het zijn, bedankt Python en Markovify! Door het pad naar het tekstbestand te wijzigen kan ik zelfs een blog in het Engels schrijven.
Nu kan ik dus een prachtige blogpost van 50 regels laten schrijven door mijn computer, nu ben ik klaar, toch?

De cloud

Ik hoor je al denken, “Sam het is 2019, waarom moet ik zelf een Python programma van acht regels in elkaar zetten?”. Je hebt helemaal gelijk, het is 2019. Applicaties draaien op onze computer is ouderwets, alles moet de Cloud in!

Vorige maand heeft Rachid Ben Moussa in zijn blog “Head first Serverless with AWS Lambda in Kotlin” geschreven over het maken van een AWS Lambda en wat daar allemaal bij komt kijken. Mijn Blogpost Generator™ lijkt een ideale kandidaat voor een eigen AWS Lambda. Het enige probleem is dat ik zelf naar de AWS console moet om zaken in te stellen of de AWS CLI moet gebruiken. Ik besteed mijn tijd liever niet aan het doorklikken van een website om zaken in te stellen en ben bang voor terminal commando’s die langer zijn dan ‘deploy’ of ‘commit’.
Wat ik niet erg vind is het installeren van NPM modules en het schrijven van een kort configuratiebestand in YAML. Toevallig is er iets dat aan mijn wensen voldoet, het Serverless Framework.

Serverless Framework

Met het Serverless Framework is het mogelijk om “event-driven functions” te schrijven en los te laten op een Cloud Provider naar keuze.
Zo’n “event-driven function” kan iets makkelijks zijn als een functie die “Hello World!” teruggeeft, maar kan natuurlijk ook iets ingewikkelders zijn, de mogelijkheden zijn eindeloos. Het is wel gebruikelijk dat één “function” één taak uitvoert, als er meer taken zijn kan een function natuurlijk weer een andere function aanspreken.

Het ideale voor iemand als ik is dat het Serverless Framework veel werk uit handen neemt. Ik hoef geen consoles door te klikken, ik configureer wat zaken in een YAML bestand, schrijf (of kopieer en plak) wat code en typ “serverless deploy” en voordat ik het weet staat iets online in de mysterieuze cloud.

De Blogpost Generator + Serverless Framework

Genoeg uitgelegd, tijd om de Blogpost Generator™ in de cloud te zetten. Als eerste moet natuurlijk het Serverless Framework geïnstalleerd worden. Dit wordt gedaan op een revolutionaire manier, namelijk met commando’s in de terminal. Hier moet Node.js overigens wel voor geïnstalleerd zijn.

Vervolgens moet een Serverless project aangemaakt worden. Serverless heeft een aantal templates die gebruikt kunnen worden, dit bespaart weer een paar minuten, top!

Dit genereert twee bestanden, een YAML bestand die gebruikt wordt voor configuratie en een “handler” bestand wat in mijn geval een Python bestand is.

Om de Blogpost Generator™ als AWS Lambda online te zetten moet ik eerst wat zaken instellen in het gegenereerde YAML bestand. Na het weghalen van de commentaarregels die Serverless standaard toevoegt en het instellen van de benodigde zaken ziet mijn YAML bestand er als volgt uit:

Er zijn genoeg zaken die ingesteld kunnen worden in het configuratiebestand van Serverless, in mijn geval heb ik niet meer dan bovenstaande nodig. De volgende zaken worden door middel van mijn configuratiebestand ingesteld:

  • Service
    Naam van mijn service, hier komt de functie onder te staan.
  • Provider
    Instellingen voor de Cloud Provider. Ik wil een functie op AWS draaien die gebruik maakt van Python 3.6, in de ‘eu-west-3’ regio draait (oftewel Parijs) en 256 MB aan geheugen heeft.
  • Functions
    Hier kunnen functies gedefinieerd worden, in mijn geval heb ik er maar één, namelijk ‘generateBlog’. De handler van generateBlog is de ‘generateBlog’ methode in het ‘handler.py’ bestand. Deze handler wordt aangeroepen wanneer er een GET request binnenkomt op het ‘/{language}’ endpoint. Language is een verplichte parameter in het pad.
  • Plugins
    Ik gebruik één plugin die ervoor zorgt dat de Markovify library meegenomen wordt tijdens het deployen van mijn functie. Markovify staat in een “requirements.txt” bestand, de plugin gebruikt dat bestand automatisch.

Vervolgens heb ik de code voor mijn handler geschreven. Zoals aangegeven in de YAML heb ik de ‘‘generateBlog” methode geïmplementeerd in het “handler.py” bestand. De code ziet er als volgt uit:

Zoals waarschijnlijk te zien is heb ik de code van de Blogpost Generator™ naar de handler gekopieerd. Ik heb alleen een paar regels code toegevoegd voor het ophalen van de “language” path parameter en het teruggeven van een paar regels JSON met de gegenereerde blog.
Ik kan natuurlijk nakijken of de gebruiker een valide taal heeft meegegeven of ervoor zorgen dat het Markov Chain Model in een bestand staat en niet steeds “on the fly” aangemaakt wordt, maar mijn luie stoel roept, dus voor nu laat ik het zo.

Nu alles ingesteld en geïmplementeerd is kan de functie gedeployed worden! Wanneer je dit zelf voor de eerste keer doet moet je nog een AWS account instellen, maar dat heb ik al gedaan. De functie kan gedeployed worden met het volgende commando in de terminal:

Serverless zorgt vervolgens voor het instellen van alle benodigdheden op AWS. De Lambda hoeft niet zelf aangemaakt te worden in de AWS Console, evenals het endpoint voor de GET request van het eerder gedefinieerde event. Na het deployen geeft Serverless informatie over de aangemaakte service terug, in mijn geval krijg ik onder andere het endpoint voor de GET request:

Wanneer een GET request binnenkomt op het gegenereerde endpoint wordt de Lambda aangeroepen, die stuurt na een paar seconden een blog van 50 regels terug.

De blog

Zo, nu hoef ik nooit meer een blog te schrijven! De volgende keer hoef ik alleen nog maar mijn functie aan te roepen en dan heb ik 50 regels aan geweldige tekst.

Om de wereld weer een stukje beter te maken heb ik een (mooie) pagina gemaakt waar ook jij een blogpost kan genereren. Zo kan ook jij tijd besparen wanneer er een blog geschreven moet worden!

Genereer hier een blog

Bekijk hier de code

19 maart 2019  |  
7 min leestijd

Kennismaken?

Luminis onderscheidt zich van andere aanbieders in de ICT door een waarde- en klantgedreven aanpak. Wij willen vooruitgang zien, zowel bij onze klanten als bij onze medewerkers. Graag komen we met je in contact om te ontdekken hoe we die kunnen realiseren.

Contact

©2019 Luminis Arnhem – Leveringsvoorwaarden

Design: Eyefun