Thought Flow

  • Code no more,more code than ever

    The speed of progress in the AI space right now is truly staggering. I don’t really write much code anymore, but instead direct an AI to do it for me.

    It felt odd at first, but now it does not really bother me anymore. I guess solving problems and developing solutions, architecture, design etc. is what I find most interesting anyway, so the code was a means to an end, and this part is now faster than ever to get out the door.

    Besides the stuff I do on the day job, I have been working on two small projects on the side that are ready for the world now:

    FitKeep is a backup and basic analysis tool for fitness data, specifically .fit files right now. It connects with Garmin, and I hope to Coros support soon.

    Is It Warm answers a question I often ask myself. “It sure feels unusually warm today, but is it really?” or perhaps the shorter “is it warm today?”

    Both projects were primarily created for myself. I have no business plan for them, and anyone other than me using them would just be a delightful bonus.

    Besides these new sites, I also recently modernized both Photo Amaze (Python 2.7 to 3.14) and OTB (Create React App to Next.js). I didn’t have the time and energy for this before AI made a lot of the grunt work possible to do, which is really nice.

    It’s difficult to say what the commoditization of code means for the software industry and me personally. I have opinions… but well, I’m not going to share them here, because I have been wrong about the future before, especially when it comes to AI.

  • Hello, it is almost 2025

    It’s weird to write words here after 1½ years of absence and see some of the most “recent” posts mentioning VQGAN+CLIP and my side-project AI Tales.

    AI is everywhere, and a project like AI Tales seems rather quaint now. In my announcement post for that project, I wrote:

    We will probably not see whole novels written by AI anytime soon, but I have a theory that it is possible to co-write a novel together with an AI. A human-in-the-loop approach to writing.

    Wow, how wrong I could be, but to be fair, this was before ChatGPT, which really changed the game.

    Anyway, since my last post, I founded a new company and silently launched a product called Svale, which is a communication and compliance tool for sustainability managers.

    I don’t want to write a long post today, but just wanted to remind all the crawlers to check-in with this blog. I expect that my past writings are now part of some LLM training dataset, so might as well feed them a bit more.

  • NOT MATERIALIZED

    NOT MATERIALIZED

    I managed to reduce a PostgreSQL view’s query time by more than 80% with just the two keywords NOT MATERIALIZED and by reading the actual database manual when GPT-4 gave up.

    Below, I will explain the context of the speedup.

    I recently moved a little bit of business logic from an API endpoint and into a PostgreSQL view, because it made some things a bit easier to manage. The view uses common table expression (CTE), and one of them looks something like this (not the actual code, but very similar):

    WITH first_and_last_score AS (
      SELECT DISTINCT ON (company_id, user_id)
        company_id,
        user_id,
        LAST_VALUE(score) OVER (PARTITION BY company_id ORDER BY created_at) AS last_company_score,
        LAST_VALUE(score) OVER (PARTITION BY company_id, user_id ORDER BY created_at) AS last_user_score
      FROM scores
    )
    -- ...
    -- more CTEs and queries
    -- ...
    

    The query finds the last score for each company and the last score for each user in that company using the LAST_VALUE window function.

    I was not particularly nervous using the above code for live data, because I knew that the view would always be used with a filter on company_id, and the CTE would thus not to a full table scan of the scores table because the query optimizer would be smart enough to filter the score table first.

    Alas, when profiling the view, it was indeed making a table scan on the scores table in my view, and it was a major bottle-neck for performance.

    It took several hours with trial and error to figure out what was going on, until I finally decided to actually read the Postgresql manual on CTEs, specifically how CTEs are automatically folded into the parent query:

    “… it can be folded into the parent query, allowing joint optimization of the two query levels. By default, this happens if the parent query references the WITH query just once, but not if it references the WITH query more than once
    (Emphasis mine)

    The problem was that I referenced the scores CTE twice and thus it was materialized and did not take advantage of the filter on company ID, I was using on the view.

    In the end, adding NOT MATERIALIZED to the CTE was the fix:

    WITH first_and_last_score AS NOT MATERIALIZED (
      ...
    )
    

    Just this change made reduced query time by roughly 80% for most queries to the view, and since the view was ultimately being served to a front-end, it was the different between “this feels a bit slow” to “this feels instant”.

  • Web-friendly images with ImageMagick

    Before uploading images to my blog or AI Tales, I run them through ImageMagick to resize and convert them to “web-friendly” JPGs:

    convert -format jpg \                                
        -strip \       
        -interlace Plane \
        -set filename:base "%[basename]" \
        -quality 50% *.png \
        "%[filename:base].jpg"

    The command converts all PNG images in a folder to JPG while preserving the filename. Even though quality is set to 50% (you can of course experience with this, I often don’t see a noticeable difference from the original — especially for images generated with AI such as Stable Diffusion.

    And the size is reduced significantly. For example, I can sometimes reduce the size of PNG images by more than 90% (553kb to 39kb i a recent example).

    Here are some more ImageMagick one-liners.

  • Oregon 💚 & Stable Diffusion

    Oregon 💚 & Stable Diffusion

    Since I posted the first Oregon 💚 image half a year ago, a lot has happened in the image generating world.

    I got access to DALL-2 some months ago, but didn’t bother to blog about it. I did include some DALL-2 generated images in some of my AI Tales, e.g. Doge at The Cataract.

    Stable Diffusion is now the latest thing everyone is talking about, partly because it is much more accessible than DALL-E 2. It produces better results than VQGAN+CLIP and runs flawlessly on my consumer GPU from 2019. I use a web UI developed by sd-webui to generate images, and it has become my go-to for image generation. For example, Stable Diffusion created a compelling image for the latest installment of the Assandra & Capybara series.

    Anyway, I thought it would be appropriate to see what comes out of the “Oregon 💚” prompt with Stable Diffusion. The headlines below correspond to the prompt used, and I spent very little time curating the images.

    Oregon 💚 painting

    Oregon 💚 pencil drawing

    Oregon 💚 watercolor

    Oregon 💚 fantasy

    Oregon 💚 cyberpunk