It's Friday!
Well, it's Friday afternoon, and I had way too much coffee, so this article will be a little light hearted ! If you're not up for it, and you want serious content.... well, I guess I have some AWS-related content you can have a look instead ๐
My dream is to have a Jarvis-like AI available in my home and help me out when I'm building my iron man su........when I'm doing aws stuff.
Today I'll show you how to remind yourself of important things that we can't live without. Things that makes to world go by, things that provide people satisfaction and a reason to live.
Yes, I'm talking about taking out the bins! Yep, that bin. Not the virtual one on your pc, but real-life one that you forgot to take out and now looks like a tower built from trash.
Here's what we'll do today:
"We'll have an AI notify us every time the garbage collector comes to take our bins away!"
Tools we'll use
We'll use the following tools for this purpose:
N8N
This is similar to Zapier. An automation framework that'll greatly simplify building this all. Why not Zapier? Because N8N can be self-hosted on my own homelab and have access to secure private information (and my home assistant setup). Also, N8N self-hosting is free, and always has been. Big thanks to the guys at N8N for making this possible!
I'll not cover installing N8N, but if you have docker installed, it takes like 2 minutes. If you don't use Docker yet....well then what are you waiting for?
https://docs.n8n.io/hosting/installation/docker/
ChatGPT / OpenAI API
Yep, we'll use the big evil here.
Yes, I don't like it either.
Yes it'd be better locally.
Do I have disposable ยฃ2000 to build a local LLM machine running at decent speed? Maybe.
Can I justify the spending for my wife? No. ๐
As a silver lining our AI masters has promised us not to use data on the API as training data, so we can be relatively safe:
Once you have openAI api access, you can generate an API key for it.
There's also a possibility to use other Huggingface models with inference (which may be actually free), but I'm not sure which model would perform well.
Telegram/Pushover/Email, whatever
So here we'll set up a Lambda function via Eventbridge and use SNS to send a text.......nah, just kidding, not on a FRIDAY AFTERNOON!
Basically just pick any notification service. Pick your preferred one. Check N8N integrations, there's around 700 different integrations.
I'll not detail this part, as it'll be different for everyone, and N8N makes it incredibly easy to set it up with whatever preference you have.
You can even have it create a reminder for you in your google calendar if you wish.
I personally use a Telegram chatbot, because I find it more flexible than anything else. An easy option as well is Pushover, which is a service for like a decade that does extremely simple phone notification. Both of them are just an API call, so it's not rocket science ๐
Oh, and both are free.
A bin collection website
For our particular area, there's a website that provides me with the bin collection dates. You type in the postcode, and it gives you a list of when it's being collected and what date.
If you don't find it immediately check the browser dev tools for any sort of API calls. If you're lucky, you'll be able to call it from your own machine. Here's how mine looked like:
Which means I can take a note of the request URL and retrieve the bin collection dates anytime I want specific to my address. Keep a note of your URL, as you'll need it later on.
Step 1: HTTP request
Not much to say here, grab the HTTP request node and have the URL pasted in with a GET request
Extract content
Get an HTML node and extract the specific content. Here I had a block of text with an ID assigned to them (I got lucky), but you can pick any CSS selectors, try to make sure it's somewhat unique and it's a dynamic element that may move around the page.
you can go on further extracting more stuff from this using even more HTML nodes and go as specific as you want. I wanted to remove my address from the response, so I made some gymnastics using a few HTML nodes and merges to do that.
At the end, this is how I made my response look:
Which resulted in something like this:
[{"response": "Friday 9th February - ResidualBin"}]
This is 2 lists, on containing the dates, other the bin types. Then with a code block, I returned the first hit, which is the next collection date and bin type.
Checking if date is tomorrow
For that I wrote a disgusting piece of code that determines if that piece of text is tomorrow. I had chatGPT generate me code. I'm not crazy enough to do this myself.
There's probably easier ways to do this, but how could we call ourselves engineers if we didn't pick the most complicated way of doing something? ๐
function isDateTomorrow(dateString) {
// Extract date components from the string
const dateComponents = dateString.match(/(\w+)\s+(\d+)\w+\s+(\w+)/);
if (!dateComponents) {
return false; // Format not matched
}
// Map month names to month numbers
const monthNames = ["January", "February", "March", "April", "May", "June", "July", "August", "September", "October", "November", "December"];
const monthNumber = monthNames.indexOf(dateComponents[3]);
if (monthNumber === -1) {
return false; // Invalid month name
}
// Create a date object from the extracted components
const year = new Date().getFullYear(); // Assuming the year is the current year
const parsedDate = new Date(year, monthNumber, parseInt(dateComponents[2], 10));
// Get today's date for comparison
const today = new Date();
today.setHours(0, 0, 0, 0); // Reset time to 00:00:00 for date-only comparison
today.setDate(today.getDate() + 1)
// Compare the parsed date with today's date
return parsedDate.getTime() === today.getTime();
}
const isTomorrow = isDateTomorrow($input.last().json.response);
const resp = { isTomorrow: isTomorrow };
if (isTomorrow) {
resp.when = $input.last().json.response;
}
return [{response: resp }]
After a tiny bit of modification it worked fine.
For every return statement please make sure it conforms to the following structure:
return [{some object}] or in our case it's: [ { "response": { "isTomorrow": true, "when": "Friday 9th February - ResidualBin" } } ]
i.e. an object (or multiple) returned in a list. If you don't do it like that N8N will complain ๐
Then once you have this, just return the value:
So for now our flow does the following:
- On being called, it returns the date of next collection, along with the fact if it's tomorrow or not.
Here's how the whole flow looks:
Step 2: AI Agent
Wow that sounds fancy isn't it? ๐
This will be your agent you can ask to do anything (i.e. you can re-use this later on for other tasks)
First of all, add your OpenAI API key to the credentials
menu on the left. It'll then apply to all further OpenAI related nodes.
A few nodes to mention that you can see on the screenshot
Execute Workflow Trigger => it's basically a node that lets other workflows trigger this workflow.
On a new manual Chat message => this will be added automatically when you add a new agent. It just means you can test the agent from this screen via a chat interface
Model: here's where you add the model you want to use. Nothing else required here
Agent: Again, nothing else here besides the value to use from the previous node, which is : {{ $json.chat_input }}
Window Buffer memory : this is to keep your Agent's conversation somewhere, so it remembers your previous message. For this guide it's irrelevant.
Tools: you can see a few tools attached. These are basically other workflows you created in N8N that the agent can use.
Here's how the tool looks like that we've created in the previous step:
Take a note of your workflow ID. That's the URL of the previous workflow you worked on.
The agent will make an educated guess on which tool to use.
Unfortunately I haven't had too much luck on complex tool usage, especially if the agent doesn't get the expected output. It just keeps on calling the tool until it gets bored. Literally.
Working with an AI Agent is like working with a kid. At least that's how it feels!
Step 3: Scheduling
This is a short step, and can be done in other ways.
I set up a schedule workflow separately that calls the Agent with a specific input:
The Schedule has a daily schedule every day 8pm. The edit fields contains the following:
with a value of: "Please check if there's bin collection tomorrow. Once you did that, send me a mobile message if it's tomorrow with the details. If it's NOT tomorrow, don't send me any message."
You can see from the above, that it kept sending me messages even if it wasn't tomorrow ๐ Yes, we got to the point where an AI agent is harassing me.
Then the last node is just to call the workflow with the specific ID.
So the full flow so far:
Schedule triggers and calls Agent
Agent gets instruction and uses bin collection tool
Bin collection tool scrapes website and returns bin date
Agent decides to send message or not based on response
(not done yet) Agent uses messaging tool to send message
As you see it's fairly simple and looking at it now I can see that the AI agent is a completely redundant part of the flow (you could just send a message straight away after "istomorrow" is true.)
But I wrote all these up already, I won't delete the entire article, sorry ๐
At least we learned how to use an agent! And N8N!
One thing is left tho, which is sending the notification to your phone
Step 4: Notification
Again, this will be different for every person, but here's my flow:
In the middle is an API call to Telegram, while you can see an error or a success node at the end to lead the Agent on the right path.
Once you have this, save it and add it as a tool for your AI Agent.
Now your AI agent has 2 tools!
That's it!
As you can see it's fairly easy to add more tools to your agent and do other stuff for you.
Let me know if you have any questions.
N8N and LLMs are something I'm actively playing with, so you can expect more of these articles in the future (besides AWS)