Smart Poi

LLMAP advanced context generation for AI coding

I use the open source and very capable Aider for AI code generation. Anyone who has tried AI code generation has heard of “context” – the information you send over to the LLM so that it can know what the code looks like that you want to modify.

Anyone using these tools eventually comes up against the dreaded token limit at some point – some sooner rather than later! The LLM can only keep so much context in memory at one time. This is annoying if you are trying to update a legacy codebase with multiple files and countless lines of code – who wants to try to pare this down to only the relevant parts, copy and paste into the window?

In Aider adding files to context is as simple as /add file.txt
To remove files just do /drop file.txt
If file.txt is 100 000 lines long you have to copy and paste the parts you want (up to 60 000 tokens), check how many you have left by running /tokens
But that is takes too long! It defeats the purpose of getting AI to do the reading and modifying for you (remember to review the diffs after!)

Meet LLMAP

llmap is “context extraction at scale”. The tool can search and sumarise vast amounts of code and ouput only the relevant parts which you can then add to your AI coding tool context – leaving out all irrelevant parts (usually most of it!)
Example from my own use case: I had an issue with a looping api request on ESP32 in my Magic Poi project – I had been concentrating on the battery monitor feature and the new feature broke some other functionality. So I did a diff with the last known working branch:
git diff origin/Battery_Monitor_Main_Merge > context_git_diff.txt

This diff is from way back though so it was too large for the context window (if you include all of the code I wanted to update) so I had to run it through llmap with a query:
echo context_git_diff.txt | llmap "list the changes made that affect the control flow of the application." > llmap_diff_context.txt

Now my new file llmap_diff_context.txt with only the relevant information could be added to the context – using /read-only since it’s not included in git nor do I want to edit it. I used /architect mode* to see what changes happened to cause the loop. Turns out it was a simple misplaced line of code and everything worked again!
*for me architect mode is configured to use DeepSeek R1 for thinking and V3 for editing – cheap and effective

LLMAP is easy to use – just install via pip. By the way, if you don’t have a DeepSeek api key, the update I recently submitted to add OpenRouter support has been merged but not yet published. You will have to download and install llmap manually to use OpenRouter – but it works.

Full credit to Johnathan Ellis for creating and sharing this great tool. You gotta love Open Source!

Android Devices

Over the years I have had many mobile devices – all on Android. This blog post is going to go through the ones that still work, and how I use them.


  1. Xiaomi Redmi 9A
    – Main phone, primary use is Google Calendar, Maps (to get to shows) and WhatsApp. Also reading.
    – Absolutely hate this phone
    – Laggy
    – Managed to update to Android 11 but with great difficulty (hacking phone because Xiaomi doesn’t want me to upgrade my own hardware)
    – Looking for a replacement (after which I will hack it some more I guess)
    – This is the last Xiaomi I will ever get – moving back to Samsung if possible (see below)

  2. Doogee Mix Lite
    – Primary use for Podcasts
    – Old main phone (got it for the camera and fingerprint reader)
    – Doogee actually pushed an update that bricked this device!
    – After that I found a LineageOS based rom called ViperOS – Android 7, the latest available for this phone.

  3. BlackView Tab 9 (10 inch)
    – Primary use: Crunchyroll (Anime), PipePipe (YouTube) and Kodi (movies and series from my local networked HDD, when we don’t use Kodi on our Raspberry Pi 400 to watch on the “TV”).
    – My son’s old tablet, battery died because he would let it run down to 0%
    Hacked it to add replaceable batteries
    – Haven’t replaced the OS yet

  4. Lenovo Tab 7
    – Primary use FlipBoard (news reader)
    – I like to read news in the morning. 7 Inch is perfect.
    – Upgraded to Resurrection Remix OS (based on LineageOS)
    – Latest available Android 7 (upgrade from 4.4 original!)

  5. Proline 7 inch
    – Primary Use: kids friends sometimes need something to play LAN MineCraft Bedrock on, or Roblox.
    – Another Tablet that my son broke (he now has a restriction on his new one) by running the battery down.
    – Replaced the battery and now it’s a backup device.
    – Impossible to update software, turns out this has a “Spreadtrum” chip inside, a low cost, rare and very bad SOC. Did come with Android 12 “GO” version, so it works at least.

  6. Samsung Galaxy Y
    – Primary use case: Radio and Music player for shows
    – my first android phone (3.5 inch!)
    – Thanks to replaceable battery it still works
    – I bricked one trying to upgrade (my wife’s old one) so this one still has Gingerbread on it (Android v3.3)
    – Processor is Arm v6!

  7. Honorable mention: Samsung Galaxy SII
    – Worked up until a year ago
    – Used as Podcast phone and for Android App testing
    – Managed to upgrade all the way to Android 12 (LineageOS)
    – Original was JellyBean (Android 4.3)
    – Hoping to get another Samsung device for next main phone, really good experience with the two I had so far.

Conclusion

I don’t have one device that does everything. I don’t buy a flagship device when I get a new phone. But I do try to make use of old devices, which offers some benefits, including extra battery life (just use the other device while one is charging) and saving money (I am especially pleased with having a 10 inch tablet for Anime, for “FREE”)

The Problem of Timelines

Problem

Definition: A clear, concise statement describing the issue to be addressed, including its scope, context, and constraints. It serves as the foundation for analysis, solution design, or decision-making.

So when I say “Problem” that’s what I mean: an issue to be addressed – the clearer the context the simpler it is to come up with a solution.

By the way, Magic Poi and SmartPoi (open source) have a Patreon Support channel . If you would like to keep track of progress – and optionally contribute (mostly to AI Coding Assistant and Server bills) please join up – you can join for free and get updates about the project, paid members get a discount when we start selling the actual project.

The Problem

TLDR: I am working on the best ways to create, save, fetch and display timed sequences of images for Magic Poi. It’s tricky but I am getting there!

Timelines and Sequences – in terms of Magic Poi:

Timeline: a sequence of images each with an attached time to be displayed. The times start at zero.

Sequence: just the sequence, timed at a regular interval.

So in terms of software, we have a User Interface running JavaScript, connected to a back end running on Python (Flask). The back end database is PostreSQL which actually contains all of the arrays of images and metadata (including ownership and relationships – eg Tom owns x.jpg and shared it with Dylan).

The Poi running C++ needs to connect to the Python server API using http requests (authenticated using JWT, so you don’t get someone else’s images!)

Currently how the flow works is:

  1. User creates timeline and saves – this adds the image ID’s in an array (each image has a number), like [1, 4, 67, 55] and the timeline times in an array (in milliseconds), like [0, 257, 1029, 40005].
  2. The back end saves the timeline image ID’s and times along with metadata (Timeline name, owner, shared with..)
  3. Now the hard part, poi fetch the timeline – after selecting “timeline” using buttons (I have created a nice menu system with 2 buttons – LED colours give indication of position in the menu, long press first button for menu, short press first button to select main menu position, short press second button to select sub-menu)

– this is where the hard part comes in. First of all, we need to know how many timelines the user has, so we need to fetch that in order to proceed. Then the sub-menu needs to have exactly that number of options to choose from. But what if we are not connected to WiFi? I have to have fallback options for every error, including Server errors (maybe the data center went down for maintenance, or I borked something in the Cloud..)

Eventually you get to the point of downloading the images (using the timeline image ID array) and then displaying after all the downloading is done in exact millisecond time, according to the timeline times array.

Also, I want the option to have the images display as a regular sequence (using another button menu option) rather than to exact timing – like the original SmartPoi did it. This is rather simpler to achieve thankfully but we still need to incorporate a new time variable which can be changed on the web interface or using buttons (or the offline on-board web interface, yes there is another one also)

Conclusion

So in case you are still following this – the timeline object is created in JavaScript, stored and served by Postgres DB and Python, and consumed by both JavaScript (web page loading) and C++ (Magic Poi download and display)

Status

Right now I have Magic Poi nested menu system which I am quite pleased with. We just finished testing on the new prototype board and everything works! In terms of software I can download and display one timeline in exact millisecond timing – or select a specific image from that timeline to display individually.

Todo

Still todo is the selection of which timeline – and also adding shared timelines to the list (the ones your friends shared with you using the easy to use right click web menu interface). And optional sequence mode, choose to display image each for 0.5 – 3600 seconds at a time before moving to the next.

Also I still need to add in the Flash storage space checks from SmartPoi (make sure we have enough space for the image files before downloading them!)

Maybe

I might even be able to squeeze in multiple timelines at once on the poi? This would require a way to check the Flash size restraints on the poi from the Server side, to enable calculations of size (some timelines might share images, so we don’t have to download multiple copies, sharing image files between timelines…) Right now I’m not worried about this though!

Also: Streaming! I already did this as a fun test but it requires the poi to be connected to WiFi the whole time. With two cores on S3 chip, one takes care of the downloading of images, the other displays. When an image completes downloading, it is immediately passed over to the other core with some cool memory swap code and displayed – while the next image starts downloading. This opens up many possibilities, and bypasses the restraints inherent in ESP32 Flash memory storage size (no I am not adding an SD card for downloads)

Conclusion

Wow that is a lot of words. Sometimes it is just good to outline the Problem in order to focus and get to the solution – which for me will be fast, efficient and reasonably priced Magic Poi, with versatile Timelines!

Rookie mistake – forgot to pin library versions!

In PlatformIO there is the platformio.ini – a really powerful tool to select versions of libraries from PlatformIO servers, and initialise settings for the whole project.
I recently had a problem where a friend was not able to compile my SmartPoi project – but it worked for me??

Long story short

I re-cloned the project myself (starting clean) and managed to reproduce the same problem my friend was having while compiling. After a lot of head scratching I realised – the libraries in my project were declared like so:

mathieucarbou/ESPAsyncWebServer @ ^3.1.5

However that just tells the compiler to fetch the LATEST version as long as it is above (^) 3.1.5 – and that particular library had a breaking change update. The reason I didn’t have a problem on my local version was because my compiler was just using the cached local version (not bothering to update every time, you can force this by doing “Full Clean” which I don’t tend to do)

Conclusion

Make sure to pin your versions, especially in code you want to share!

My new platformio.ini now has lib_deps that look like this:

ESP32Async/ESPAsyncWebServer @ 3.7.4

Go and get the latest ESP32 SmartPoi now

git clone https://github.com/tomjuggler/SmartPoi-Firmware

cd SmartPoi-Firmware

git checkout -b ElegantOTA_CombinedS3C3_PlatformIO origin/ElegantOTA_CombinedS3C3_PlatformIO  

SmartPoi Controls Android App updated

Android App now available for download!

I finally managed to get this working on *most* of my devices.

When it works, it’s great – upload from your phone/tablet, control with indication of connection, sliders for brighness and more! See previous blog post for details of how this all looks (it’s the same on Android, except for drag-and-drop uploading which is not possible)

DISCLAIMER: Android is a vast collection of different versions and capability devices. I used to do Android apps in the Play Store and gave up, because things break a lot. This app is just a web app inside a container and won’t do anything to your phone but it might not work – especially the uploading part.

Links: Android 12+ devices: https://circusscientist.com/SmartPoiControl_Apr_25.apk

Android 7-10 devices: https://circusscientist.com/SmartPoiControl_Apr_25_Older_Android.a
pk

Android 11 phone: Try both? Neither version works on my Android 11 phone. Actually not sure about Android 8/9/10 either. I tested on Android 7, 11 and 12 only.

And yes, I am aware that I am living in the future (named the app Apr 25 in March).

Thanks to my Patreon supporters!

More people are joining up – it’s free! You don’t have to pay to support me on Patreon, but my paid supporters are helping out a lot, particularly with my AI coding assistant bill. Without AI coding assistance this app wouldn’t be possible, and without my supporters there wouldn’t be money for the api’s.

Patreon supporters (free and paid) get the latest news first! https://www.patreon.com/c/CircusScientist

SmartPoi JS Utilities Update Demo

I just uploaded a full walkthrough of the updates to YouTube. Some functionality is not obvious, but the uploads are faster, and connection is more reliable. Overall I am quite proud of this version.

Next up: port the improvements over to the Android App.

To support my ongoing work on the SmartPoi and Magic Poi projects (and to help me save up for a new Microphone!) please consider contributing to my patreon. https://www.patreon.com/c/CircusScientist.

Shout out to Flávio from my Patreon, this one is for you!

Special Notice:

In the next month or so all of my paid subscribers over on Patreon are going to receive a surprise. I have something that nobody has done before (I checked) but I’m keeping it for them, so now is a good time if you like poi and making stuff, go ahead and join up.

Building 10 websites at once using AI

Using Aider AI coding assistant and Deepseek api I got 10 usable websites made in about 30 minutes. This is just a test of what is possible with AI coding – the only things I did on the websites in the video was add a few images to make them work.

To have your website created and hosted with the help of AI visit https://devsoft.co.za – obviously if you pay me I will do it properly!

I think above all this video demonstrates that AI is a tool, but needs proper guidance to get it right.

The Details

I made a script which used Aider:

*I found the problem I had in the video now – no mention of image file format!

#!/bin/bash                                                                                                                                                                                                      
                                                                                                                                                                                                                  
set -eo pipefail                                                                                                                                                                                                 
shopt -s nullglob
                                                                                                                                                                                                                  
 # Configure Deepseek API                                                                                                                                                                                         
 export AIDER_MODEL="deepseek/deepseek-reasoner"
 export DEEPSEEK_API_KEY="$DEEPSEEK_API_KEY"                                                                                                                                                                
                                                                                                                                                                                                                  
 # Process each website folder                                                                                                                                                                                    
 for dir in */ ; do                                                                                                                                                                                               
     (                                                                                                                                                                                                            
         echo "Building website in: $dir"                                                                                                                                                                         
         images=("${dir}images"/*)
         # Use aider to build website from brief.txt (paths relative to git root)                                                                                                                                                              
         aider --yes-always --no-auto-commits --no-stream --message "$(printf "Make a website (or improve the existing site) using the following instructions. Make sure to use only the images in images folder (they are always named img img1 img2 etc) when building the site. If any other images are referenced, remove them. Do not leave the website unfinished, add placeholder content where an unfinished element would be always. \n\n%s" "$(cat "${dir}brief.txt")")"  "${dir}index.html" "${dir}script.js"  "${dir}styles.css" "${images[@]}"
     )                                                                                                                                                                                                            
 done                                                                                                                                                                                                             
                                                                                                                                                                                                                  
 echo "All 10 websites built successfully!" 

This used in particular the brief.txt in each website folder. here is an example from the video:

Custom Candle Maker: Wants a moody, scent-driven design with a product carousel, an ingredient transparency section, and a "Build Your Candle" form (wax type, fragrance, color). Mentioned competitors using "slow-motion pour videos" but prefers static images to save costs.

The 10 prompts were made using Deepseek chatbot, which I asked to create customer requirements for the 10 videos – with variety.

Conclusion

The AI does a good job but needs a lot more information than the vague short prompts I actually gave it. In a real-world scenario with an actual customer I would most likely be much more specific, with better results no doubt.

It was fun to watch, however!

Moving On

TLDR:

Some old Circus Scientist services have to go, in order to move forward with new projects. This is due to Ubuntu Server upgrade (not intentional)

Outline:

There are two ways to look at things in software:

  1. Keep things compatible and working no matter what. I think of this as the “hoarder” mentality (think Microsoft)
  2. Move fast and break things (aka Google)


I guess I try to keep a happy medium, leaning towards the “hoarder” side. Right now though, something is going on that I don’t have any power to change. The Ubuntu Server version 20 which I have most of my “experimental” services on is going EOL in a few months.
I don’t have a choice – I need to upgrade all of my online projects. Sometimes this is as simple as upgrading Ubuntu in-place but due to Python version updates this time it’s impossible. Each service has to be updated and put on a new version of the server – I’m using the latest LTS version, Ubuntu Server 2024.

What is going away

  1. LED Website Indicator. I really love this project, my first fully integrated Web and IOT project. Basically nobody cared except me. I’m going to open source the Arduino code at some point, some parts are already are available on GitHub.
  2. MagicPoi old website. There is already a new version with most of the same functionality (my patreon subscribers have had access to this for a while). This was my first really large Flask website with an api accessible from ESP8266 and is a bit old and insecure now. I have a backup if anyone has data from there that they need to get back, just send me an email and I will sort you out.
  3. AI Site Generation. A fun project that was just for learning purposes really.
  4. Monkey Detector (web version with api). Another learning project, not being used.
  5. K8 Juggling. Very old fun service.
  6. Invisible Deck Practiser. Just a JavaScript version of an Android app (magic).
  7. Other personal sites not related to this blog.

Temporary disruptions

Several other services need to be migrated, this may take up to a week depending on the complexity. Expect disruptions.

  • SmartPoi Downloader
  • The new alpha version of magicpoi site (with api)
  • devsoft.co.za
  • show.circusscientist.com
  • Other personal sites not related to this blog.

Conclusion

Sometimes you have to break things in order to move forward.

Everything that is moving to the new server is going to have proper Python virtual environments with up-to-date libraries. More secure, faster, future proof.

I cloned ChatGPT Operator using DeepSeek R1

Operator is in the news – one of my friends recently shared a video of someone using it to buy stuff online. It runs on ChatGPT 01 or 03 reasoning model. DeepSeek R1 is just as good, right? Let’s clone it!

How I did it

  1. Found a tutorial online
    – of course I’m not the first person to try this
  2. Add the tutorial webpage to Aider context (to send to DeepSeek)
    I did skim it first, looked OK, using cool libraries and stuff
  3. Add some specifications (prompt) and tell DeepSeek to make it for me.
    using Python with Gradio and Browser Use – a way to control Chrome easily with AI.

The result

DeepSeek with Aider’s “Architect mode” did an amazing job. It required some guidance about what exactly I wanted – the tutorial was more of an inspiration than something I wanted to copy exactly. As usual there were errors and I had to spend a few hours asking the AI to debug code – as well as doing it manually on occasion. AI programming is not foolproof and will not replace us in it’s current state – it’s a tool only. A great tool – but only a tool.


I love good tools.

DeepSeek decided that it needed to record it’s progress as a gif, made up of screenshots. I didn’t ask it to do this, and it wasn’t mentioned in the tutorial either.

Here is the slideshow for “Find me the cheapest Android phone on gumtree”. It also returned the results in text format.

Conclusion

It was super fun asking my “DeepSeek Operator” to do something and then watching it click around in the browser, even working out that it had to accept cookies before continuing!

As you can see, the tools for this type of operation exist in the Open Source world already. I think that Agentic AI is almost ready to take over the browser and do a lot of your work for you – if you are willing to trust it. It could be great for research for example.

Having said that, the DeepSeek R1 model was pretty slow via api. I think that may be a problem with reasoning models in general, though. Also, it didn’t find the actual cheapest phone, I did that myself in a few seconds afterwards to double check the result.

What do you think, should I publish my Python powered OpenAI Operator clone to GitHub?

Update:

I published it! You need a DeepSeek api key for this to work*

DeepSeek Operator on GitHub

*currently the service is down again, hopefully they will find a way to scale it soon