justinlillico.com

Jan 06, 2025

AI and The Future of Software Developers

Introduction

Hello friends. Welcome to my blog once more. I want to share a couple of thoughts that I've been having about AI and how it's poised to potentially take away a lot of jobs and create redundancies across a large range of the population. It was a long time ago when developers such as myself thought that we would be last in this race to the bottom.

This is one of those times that looking back with hindsight, it's very difficult to understand why we thought that now. It seems very clear that intellectual work would be the first to go. We always assumed that simple tasks like picking up a parcel and moving it to another spot would be easily automatable. In some ways, this is true, but not really with pure artificial intelligence. This is more of a robotics-type problem to solve. This all being said, I have had some existential fear with the recent unveiling of OpenAI's o3 model and how they are able to reason and absolutely smash the ARC-AGI benchmark.

Artificial general intelligence, of course, is the real game changer as it would be able to solve all sorts of problems—novel problems that humans have yet to solve. This is a fantastic milestone and somebody in my position definitely welcomes this new technology as it could save countless lives and change the future for the better. As with any new technology, however, it is also capable of making things worse. The full story, it would seem—as has been proven time and time again in the past—is that it will be a bit of both. Or a lot, in this case. I am hopeful we will be able to mitigate a lot of the risks and move into the future in a positive way.

My particular concern is losing the ability to work in this industry and all of the years of skills I've developed over time. I love working on these kinds of things and I would hate to be replaced by the very technology I sought to create. Oh, the irony.

Why would a business owner need someone like me in a post-AGI world anyway? All they need is a computer, after all, and they can just ask it to solve a problem or to build a codebase or to build them a website, and it just goes. It may take hours to start with and cost thousands of dollars, but this will go down over time. It's eventually going to get to the point where it crosses some threshold where it is more feasible for an employer to have one of these subscription services than to hire someone like me to do the job.

So, I've recently had some thoughts that somewhat put me at ease. I'm still trying to rationalize my way through the issue, but I think, at least in the short term, there are some considerations that we can entertain. That being said, we are dealing with the future here and therefore it's very difficult to predict with any real accuracy. So take everything I say here with a grain of salt.

Trust

The way things are going to go is that some new technologies are going to pop up and others are going to pop off. It is very unlikely that anything that I try to predict is going to be that accurate, but here it goes. Companies and businesses are built on trust among the members of a given business.

The reason that a key stakeholder will ask someone like me to do something for them is because they trust two things.

  1. That I am competent at what I do.
  2. That I have their best interests in mind.

So that's an interesting concept—the concept of trust. Now, what kinds of things can you trust? What is trust? Basically, it comes down to assuming that another entity will behave in a predictable manner which is in harmony with your own interests. I have enough experience with ChatGPT to know it cannot be trusted, as it frequently hallucinates and makes mistakes. So when I go to ChatGPT and I ask it to solve a problem for me, I don't trust it. And the reason I don't trust it is because I know that it's fallible, and that it's a machine.

The fallible part presumably is going to become less of an issue as time goes on. It could conceivably get to the point where ChatGPT is never wrong. Even then, we now have to deal with the fact that a key stakeholder is not always going to be able to articulate what they want. They might think they need X, when really they need Y. The XY problem, which is a topic for another day.

In this scenario, the model goes and does what it's supposed to do, but it doesn't actually solve your problem. It solves some problem you don't actually have, and you're stuck in this infinite loop where you can't quite get what you want out of the AI because you don't really know what you want, but you think you do.

In those situations, you're going to need somebody that you trust to bridge the gap between you and the AI—somebody that you go, "Hey, I know that you have my best interests in mind and you understand how this underlying technology that's been written by these machines works." And they can go in there and find the exact spot where the reasoning's wrong.

Then the developer will say, "Oh yeah, this is actually what we mean to do. Let's change this part of it." They can even work with this AGI or whatever to make it work. But my point is, I think people in positions of making key architectural choices are fairly safe in this regard.

But how will the entry-level developers that don't yet know anything fair? Unforuntely, that area will grow smaller and smaller which seems to already be happening. It's going to get much harder to get real world experience. I suppose this has happened in other fields before, so I would be interested to hear about any paralells that can be drawn. But making architectural decisions and really high-level movement of direction in codebases is still going to have to have some trusted human entity that can bridge the gap between key stakeholders and the AI.

So this really raises the key issue here: Can you get to the point where you trust an AGI? Say it gets things 99.99% right. But that 0.01% of the time that it's wrong, you can't do anything because you don't know anything about the domain of development. You need someone that knows something about their own development now.

And the second scenario is: say the AGI gets things 100% right all the time. Like I said before, you are still a fallible human, asking the wrong things sometimes, not knowing what you want. Maybe you ask for a website to be built that can take users' credit card details, when really what you actually needed was a payment gateway that already exists. But you went out and built this thing that actually exposes dangerous information to the internet because you weren't specific enough with the AI about what you wanted.

You just aren't going to be able to—nor should you be expected to—provide adequate information to the AI to get it right 100% of the time. Will there ever come a time where we can trust the AI to make all of this work without the help of human beings? This question really interests me because I do believe that using silicon, copper, and whatever else you use to make circuits, you should be able to achieve, using a Turing complete machine, a conscious entity. Particularly because I think consciousness is actually the key factor when it comes to trust. You can trust something that you believe feels. You can trust something that you believe has conscious thoughts.

You can trust a cat, but you can't trust a robot vacuum cleaner. In some sense, you know the robot vacuum cleaner is going to do exactly what it's told all the time, so you can trust it in that way. But can you trust that it's going to come home when it goes missing?

I don't know if this analogy works here, but my point is, I think largely trust between humans in a business works because you trust that they are like you, that they have conscious experience as well, and that they are aligned with your values. And at the moment, with where we're going with AGI and AI, we are not developing anything that has emotions.

We are not developing anything that has the best interests of anyone but perhaps OpenAI in mind. And for that reason, high-level developers, I think, are going to be required in the near future.

Nov 13, 2024

Choosing Between Third-Party Applications and Internal Development

When deciding whether to use a third-party application or develop a solution in-house, several factors come into play. If a third-party solution meets your needs entirely, it's often the best choice due to its reliability, cost-effectiveness, and the transfer of maintenance responsibilities.

However, third-party solutions may not always align with your requirements, or they may not exist. In cases where a third-party tool lacks the necessary features or speed, like integrating Maropost with Shopify at a faster sync rate, developing an in-house solution becomes a viable option.

Concerns about in-house development often center around maintenance. While initial development may encounter bugs or misunderstandings, thorough testing can iron these out. Maintenance fears are often exaggerated; most tools connect to APIs, which are versioned and provide ample time to adapt to changes.

The major benefit of in-house development is customization. You can tailor the solution to your exact needs and adjust it over time as requirements evolve. This flexibility allows for ongoing refinement, ensuring the solution remains aligned with your business objectives. Unlike third-party applications, which might dictate specific workflows or functionality, an internally developed tool puts you in control, providing the agility to adapt to changes in your industry or company operations.

If you are a small business, it's wise to start with predominantly external tooling, as this allows you to save on costs, focus on your core offerings, and benefit from the reliability and support of established tools. However, if you are a disruptor in your industry, then almost by definition, you will need some custom tooling to support the unique processes that set you apart. As your business grows, you may naturally become more rigid due to the layers of complexity and bureaucracy that come with expansion. This rigidity makes custom tooling increasingly essential, providing the flexibility and adaptability needed to maneuver within a competitive landscape. Custom solutions enable you to maintain a degree of agility, ensuring that your business can respond effectively to market changes and sustain its competitive edge.

In summary, the decision to build in-house versus buying a third-party solution should weigh factors like cost, time-to-market, maintenance, and customization needs. By evaluating each option's pros and cons, businesses can make strategic decisions that align best with their operational goals. In general, outsource when:

  1. An existing tool fulfills > 90% of your needs.

  2. The provider is a trusted and reputable player in their domain.

  3. It is financially viable.

If any one of these criteria is not met, serious consideration should be given to internal solutions.

Jun 24, 2024

Home Assistant Power Monitoring

So I think I have integrated aurora's delayed power usage data into home assistant, though it's a little convoluted and dodgy. Aurora is pretty much the only power provider in Tasmania.

The issue is that they post your power consumption to their non-official API the day after. This is incompatible with Home Assistant's real-time monitoring. But I did it anyway.

Firstly, we need a way to get the information from that API. Recently, they introduced 2FA which sends a text to verify. Thankfully, there exists AuroraPlus, which is a fork of a library which worked before the 2FA wrecked everything. It contains a lot of goodness, but for my purposes, getting the token using the script is sufficient.

def get_token():

    api = auroraplus.api()

    url = api.oauth_authorize()



    print("Please visit the following URL in a browser, "

          "and follow the login prompts ...\n")

    print(url)



    print("\nThis will redirect to an error page (Cradle Mountain).\n")



    redirect_uri = input("Please enter the full URL of the error page: ")



    token = api.oauth_redirect(redirect_uri)



    print("\nThe new token is\n")

    print(token)



    print("\n The access token is\n")

    print(token['access_token'])

Now we can grab yesterdays data, we need to get it into home assistant somehow. This was the most challenging, but in the spirit of doing as little work as possible, I stumbled on this repository: https://github.com/klausj1/homeassistant-statistics

It basically takes a specially formatted csv in the root directory and imports it into Home Assistants statistics database, which is used by the energy dashboard to display usage.

From here, we just need to do the T in ETL (extract transform load). So I wrote a pyscript script in pyscript to be ran as a service.

import json

from datetime import datetime, time, timedelta, UTC

import pytz

import pandas as pd

import requests

import logging

from functools import partial



# For testing, this SQL can be helpful:

# select max(sum) from statistics s inner join statistics_meta sm on sm.id=s.metadata_id where statistic_id = 'sensor:aurora_tariff_41_v2_cost'



FILENAME = "aurora_yesterday.csv"

AUTH_KEY = "THE_KEY"



logger = logging.getLogger(__name__)



TARIFFS = {

    "31": {

        "price": .29947,

        "sensor": "sensor:aurora_tariff_31_v2",

        "sensor_cost": "sensor:aurora_tariff_31_v2_cost"

    },

    "41": {

        "price": .19447,

        "sensor": "sensor:aurora_tariff_41_v2",

        "sensor_cost": "sensor:aurora_tariff_41_v2_cost"

    }

}



def date_convert(d: str) -> str:

    return datetime.strptime(d, "%Y-%m-%dT%H:%M:%SZ").replace(tzinfo=pytz.utc).astimezone(pytz.timezone("Australia/Hobart")).strftime("%d.%m.%Y %H:00")



def _get_last_sum(df: pd.DataFrame, column_value: str) -> float:

    # Doing this in a dumb way because computers fucking suck...

    # Here is what i wanted to do df[df["statistic_id"] == sensor].iloc[-1]["sum"]

    # But for some reason `ValueError: The truth value of a Series is ambiguous. Use a.empty, a.bool(), a.item(), a.any() or a.all().`

    # It is assumed these are in assending order.

    latest_sum = None

    for _, row in df.iterrows():

        if row["statistic_id"] == column_value:

            if latest_sum is None or row["sum"] > latest_sum:

                latest_sum = row["sum"]



    if latest_sum is None:

        raise Exception("There is no latest sum for " + column_value)

    return latest_sum







async def get_last_sum(sensor: str) -> float:

    try:

        df = await hass.async_add_executor_job(pd.read_csv, FILENAME)

        return _get_last_sum(df, sensor)

    except FileNotFoundError:

        return 0



@service

async def extract_aurora():

    output = []



    headers = {

        "Authorization": f"Bearer {AUTH_KEY}",

        "Accept": "application/json",

        "User-Agent" : "Mozilla/5.0 (Windows NT 10.0; Win64; x64; rv:125.0) Gecko/20100101 Firefox/125.0"

    }



    url = f"https://api.auroraenergy.com.au/api/usage/day?serviceAgreementID=YOUR_SERVICE_AGREEMENT_ID&customerId=YOUR_CUSTOMER_ID&index=-1"



    r = partial(requests.get, url, headers=headers)



    result = await hass.async_add_executor_job(r)



    data = result.json()



    data = [x for x in data["MeteredUsageRecords"] if x["KilowattHourUsage"]]



    for tariff_key, tariff in TARIFFS.items():

        kwh_state_running_total = 0

        kwh_sum_running_total = get_last_sum(tariff["sensor"])



        cost_state_running_total = 0

        cost_sum_running_total = get_last_sum(tariff["sensor_cost"])





        for element in data:

            kwh_state_running_total += element["KilowattHourUsage"][f"T{tariff_key}"]

            kwh_sum_running_total += element["KilowattHourUsage"][f"T{tariff_key}"]



            cost_state_running_total += element["KilowattHourUsage"][f"T{tariff_key}"] * tariff["price"]

            cost_sum_running_total += element["KilowattHourUsage"][f"T{tariff_key}"] * tariff["price"]



            output.append({

                "statistic_id": tariff["sensor"],

                "unit": "kWh",

                "start": date_convert(element["StartTime"]),

                "state": round(kwh_state_running_total, 2),

                "sum": round(kwh_sum_running_total, 2)

            })



            output.append({

                "statistic_id": tariff["sensor_cost"],

                "unit": "AUD/kWh",

                "start": date_convert(element["StartTime"]),

                "state": round(cost_state_running_total, 2),

                "sum": round(cost_sum_running_total, 2)

            })



    fn = partial(pd.DataFrame(output).to_csv, FILENAME, index=False) # This should be able to be a lambda, but fuck no apparently.

    hass.async_add_executor_job(fn)

    logger.warning("Complete?")

Now a simple automation combining both services and we have it going. Nice one.

← Previous Next → Page 2 of 12