AI Code Won’t Be for Humans Much Longer (AI impressions, part 2 of 5)

This is the second part of the series “Impressions of Our Current AI Usage”, as outlined by the introduction article.

In the first years of software development, the word “source code” didn’t exist, because code was just that: encoded machine instructions. How they were encoded changed rapidely, from flipping bits in the RAM directly by mechanical switches over feeding paper tapes with punched holes to magnetic storage. But for a long time, we worked with none or little abstraction over the actual machine code. I remember assembler code listings that had two columns of text: the first column for the computer, the second one just translating the first column into human-readable text.
And even with this little bit of clarification what the code actually does, we already needed additional software that took our source code and translated it for the machine.
With the adoption of higher-level programming languages, the additional software stack grew in depth until the distance between the source code and the actual machine instructions was big enough to warrant an intermediate layer of representation. Programming languages like Java or C# put a “byte-code layer” between our textual source code and the binary machine code. The machine we program against is no longer a real computer, but a “virtual machine” or in better words, a model of a machine. As long as we write source code that works correct with the model, we can assume that all the translation layers will find a way to run it correctly on the real computing substrate.
We are used to this kind of programming. We describe our goals using the machine model and a sophisticated machinery of software and hardware parts make it happen.

Forward to today and we use artificial intelligence (or inference using another kind of “model”) to produce source code in our favorite programming languages by describing our goals in even broader terms than before. We might mistake our prompts for natural language and think that we are able to produce source code by just saying what we want.

The question that poses itself nearly instantly is: If we invented a device that transforms natural language into machine behaviour from scratch today, would we include all the intermediate layers into its inner works? Is it really a good idea to transform natural language into higher-level source code, compile the source code into byte code and do all the weird magic to come up with a sequence of machine instructions that resemble the byte code? Isn’t it more efficient to teach the inference how the actual machine works and let it program directly?
Or, asking from the other side, who is the target audience of the generated source code if nobody reads it and the compiler only parses it once? Why does the inference invent all the variable and method names when the compiler throws them away again in the first step of its processing? Of course, right now the inference only imitates our way of working. But we work like we do because we write source code for other humans. If the human at the helm can’t read any layer of code anyway, why not jump directly to the most obscure representation of code and skip all the readability requirements?

As soon as the inference doesn’t imitate but actually learns about the target computing substrate, it will produce working code that is undecipherable for human readers, but optimal for the machine. (If you want to experience this effect in a tiny dose, I encourage you to play the “TIS-100” programming game). And because most inference users don’t need the readable code anyway, they won’t miss anything and get faster solutions with less hassle.

So my guess is that today’s source code will be a dying art, invented for humans and ignored by the machines because it doesn’t provide anything useful for them. The source code of the future will be less readable, more enigmatic and probably more efficient for the machine. Which means that human intervention or even just participation in the software production process will become more cumbersome and therefore even more limited.

My sorrow is that this distancing of the programming process from actual human oversight might provide a hard depedency on inference work alone. It would mean that humans aren’t just scales slower than the inference, but actually incapable of doing its work by hand anymore.

Computing gets fuzzy again (AI impressions, part 1 of 5)

This is the first part of the series “Impressions of Our Current AI Usage”, as outlined by the introduction article.

In the early days of computing, the mechanism that actually works on the data often was an analog technical device that had a certain kind of fuzzyness to it. Think about paper tape with punched holes as longterm storage: If the paper feeder was not aligned with the distance between the holes, there might be spurious variations in the code. Or, a real possibility from my own childhood: You could store digital data on music tape, an inherently analog storage medium. If the loading process succeeded relied on a mixture of patience, delicate handling, room temperature and luck. Most computing devices had specific analog/digital conversion gateways for the periphery, for the display (a very mechanical cathode ray monitor) and even for their own calculation units. The foundation we built our digital world on was influenced by sunshine, moisture, electrical isolation and lots of other factors that could influence the results. I remember a story about the early mainframe computers where a specific bug only appeared if somebody stepped on the physical floor tile where the cables ran beneath. The pressure change altered the physical properties of the cables which resulted in transmission errors.
Over the years, the physical aspects of computing slowly went away or at least faded into the background. We no longer joked about “cosmic ray errors” because the computing substrate was reliable enough to produce the same result regardless of environmental influences. The world got repeatable and therefore, predictable. We got comfortable with machines that were dumb, but reliable. If they had learnt a functionality, they could repeat it virtually forever, without the slightest variation. We had the precision of a nanosecond clockwork and the determinism of a written story that plays out the same every time it is read.

In the early 1990s, there was the first attempt to soften this black-or-white logic fabric up again. The term “fuzzy logic” was all the hype for a few years. Products like cameras, coffee machines, toasters and even water boilers were marketed as “enhanced by fuzzy logic”. How exactly the coffee got better by miniscule variations in the production process was up to your imagination. The core belief of fuzzy logic was that if we express a formula or algorithm by categorized terms instead of numbers, we could bridge the gap between “gut feeling” and digital mathematics.

In my opinion, the same thing happens again with artificial intelligence as the fuzzy component. I doubt that it disappears as thoroughly as fuzzy logic vanished, but the core belief seems to be the same. If you describe a problem in layman’s terms to an “inference”, it finds a solution that appears to be acceptable. If you describe the same problem again tomorrow, the solution might vary in detail or even in grand concept. What works today might not work anymore tomorrow or work even better. The quality of results rely on “the environment” again, not only on the input. The operating units of computing cease to be deterministic again. Computing gets fuzzy once again.

There are some immediate problems that I see with this approach:

  1. Every quality promise comes with severe limitations: The machine will work as expected today, but it is unclear if that extends very far into the future. The current results vary a bit, but might vary tremendously going forward. If the inference unit isn’t included into the product, it might not work anymore soon. Or it works noticeably different from now.
  2. The machine might change its personality on a whim. This is a problem already with encompassing updates every now and then. My smartphone itself stays the same, but the graphical presentation, usage paths and functionality changes over the course of months, if not weeks. In a world where we are used that a stone acts like a stone, a kitchen timer stays a kitchen timer and a text editor doesn’t turn into an e-mail client, we begin to lose that certainty. Our digital assistants begin to have “phases” with decreased alignment to our use cases. Or, expressed as a positive, we can hope that our digital assistants get to know us better and tune themselves in to us.
  3. We enter a world with limited transferability. One benefit of strict specifications is interchangeability. If you change one capacitor in music electronics, the sound changes (or so they claim). If you change one transistor in a digital circuit, the result stays exactly the same, because the change doesn’t cause enough variance to toggle from “black” to “white”. If the building blocks if your system are less specified digital entities like inference providers, you can’t exchange one against another without possibly altering the system’s behaviour in a noticeable way. This makes the reproducability of an equal system with slightly different components more of an adventure. You just don’t know beforehands that it will work.

There are probably more problems and maybe a lot more advantages to this approach than I can fit into one blog post. My main point is that we layered a strict, digital computing substrate on a messy, analog electronics layer and now put another layer of blurry looseness on top of it. Building future systems on this level might feel like engineering the analog systems of the past. I find it interesting (and ironic) that we try this approach right the moment when the last analog technology heroes step back and take their expertise with them.

Impressions of Our Current AI Usage (part 0 of 5)

There is a lot of hype, noise, love and opinion about the use of artificial intelligence (in all its different forms) in software development. Of course, similar disturbances happen in other markets and academic fields at the same time, but I’m not qualified enough to participate in discussions there.

I feel confident enough to share my impressions on our current usage patterns of AI here. You probably recognize the amount of limitations I put into my statement. The usage patterns evolve quick and still quite radical. I’m no “AI native”, so all I say are just impressions from a certain distance. But I felt confident enough in software engineering for at least 25 years to teach it to the next generations of developers. So I know where we were when it all started.

My impressions will be described in detail in five blog posts, each discussing one specific topic. This is the starting post that introduces the headlines of the following articles, but won’t detail them. If you want to react and comment on a topic, please attach it to the matching blog post so we can keep the discussion on point. I invite you to think along, starting with the headline statements. My thoughts are worthless without your thoughts enriching them with your knowledge and experience.

Let’s have a look at the five impressions:

  1. Computing gets fuzzy again. The components of software systems were never sharply defined, but with AI they tend to act like analog components, having bad days and noisy episodes and all.
  2. Source code gets obscure again. As soon as the AI surpasses the imitation stage of human-written code, we won’t be able to read the generated source code anymore – if the AI bothers to generate source code at all and doesn’t leap to machine code directly.
  3. Software developers don’t create software anymore, they manage and lead software creators. This was the fate of the “senior developer promoted to middle management” all the time, but at least it was humans to lead and manage and not a people-pleasing machine.
  4. We delegate the scalable and fun part of our work to AI. The infamous “10X developer” is now a “1000X AI developer”, but the tedious rest of the work (that exists and makes all the long-term difference) is still up to humans.
  5. The means of production are centralized again. Software development was a profession with incredibly low entry bar (a notebook and a coffee). The actual difference was the skill of the human that did the (mostly intellectual) work. If we all use the same AI (created and provided by infrastructure no single person could just copy), the skill difference will be much smaller and we tend to be interchangeable “workers”.

I don’t expect you to understand my thoughts by just two sentences alone, so stay tuned for the elaborate explanation in the topic-based blog posts of this series.

Topic 1 and 2 focus on technical aspects of software development. Topics 3 and 4 have the remaining human developer in mind, gauging her or his well-being and the skills needed to master a normal workday. Topic 5 broadens the view to economic and even political implications of the changes.

Topic 5 is where I might be wrong the most, because I lack the experience of living through severe changes on the scale that my anticipated changes operate on. I’m not a historian, so I’ll talk about things I only have wikipedia-level knowledge about. I hope that the thoughts are still useful and somebody can provide more content on the topic.

The topic-based blog entries are published in the next weeks or months. I will link them in the list above as soon as they are online. I really appreciate your thoughts, in the form of your own blog entry or a comment.

AI is super-good at guessing, but also totally clueless

AI is still somewhere in its hype phase, maybe towards the end of it. Most of us have used generative AI or use it more or less regularily.

I am experimenting with it every now and then and sometimes even use the output professionally. On the other hand I am not hyped at all. I have mostly mixed feelings (and the bad feelings are not because I fear losing my job…). Let me share my thoughts:

The situation a few years/months ago

Generative AI (or more specifically) chatgpt impressed many people but failed at really simple tasks like

  • Simple trick questions like “Tom’s father has three children. The first one is called Mark and the second Andrea. What is the name of the third child?”
  • Counting certain letters in a word

Another problem were massive hallucinations like shown in Kevlin Henney Kotlin Conf talk and completely made up summaries of a childrens book (german) I got myself.

Our current state of generative AI

Granted, nowadays many of these problems are mitigated and the AI became more useful. On the other hand new problems are found quite frequently and then worked around by the engineers. Here are some examples:

  • I asked chatgpt to list all german cities above 200k citizens. It put out nice tables scraped from wikipedia and other sources, but with a catch: they were all incomplete and the count was clearly wrong. Even after multiple iterations I did not get a correct result. A quick look at the wikipedia page chatgpt used as a source showed a complete picture.
  • If you ask about socially explosive topics like islamic terrorism, crime and controversial people like Elon Musk and Donald Trump you may get varying, questionable responses.

More often then not I feel disappointed when using generative AI. I have zero-trust in the results and end up checking and judging the output myself. In questions about code and APIs I usually have enough knowledge to judge the output or at least take it as a base for further development.

In the really good “IntelliJ Wizardry with AI Assistant Live” by Heinz Kabutz online course we also explored the possibilities, limits and integration of Jetbrains AI assistant. While it may be useful in some situations and has a great integration into the IDE we were not impressed by its power.

Generating test cases or refactoring existing code varies from good to harmful. Sometimes it can find bugs for you, sometimes it cannot…

Another personal critical view on AI

After all the ups and downs and the development and progress with AI and many thoughts and reflections about it I have discovered something that really bothers me about AI:

AI takes away most of the transparency, determinism and control that we as software developers are used to and sometimes worked hard for.

As developers we strive for understanding what is really happening. Non-determinism is one of our enemies. Obfuscated code, unclear definitions, undefined behaviour – these and many other things make me/us feel uncomfortable.

And somehow, for me AI feels the same:

I change a prompt slightly, and sometimes the result does not change at all while at other times it changes almost completely. Sometimes the results are very helpful, on another occasion they are total crap. In the past maybe they were useless, now the same prompts put out useful information or code.

This is where my bad feelings about AI come from. Someone, at some company trains the AI, engineers rules, defines the training data etc. Everything has an enourmous impact on the behaviour of the AI and the results. Everything stays outside of your influence and control. One day it works as intended, on another not anymore.

Conclusion

I do not know enough about generative AI and the mathematics, science and engineering behind it to accurately judge or predict the possibilities and boundaries for the year to come.

Maybe we will find ways to regain the transparency, to “debug” our models and prompts, to be able to reason about the output and to make generative AI reliable and predictable.

Maybe generative AI will collapse under the piles of crap it uses for training because we do not have powerful enough means of telling it how to separate trustful/truthful information from the rest.

Maybe we will use it as assistants in many areas like coding or evaluating X-ray images to sort out the unobtrusive ones.

What I really doubt at this point is that AI will replace professionals, regardless of the field. It may make them more productive or enable us to build bigger/better/smarter systems.

Right now, generative AI sometimes proves useful but often is absolutely clueless.

Trying ChatGPT as a professional software developer

We are a company of software developers that does not sell a product but provides a wide range of services. Our primary service is developing individual software or maintaining existing software for our customers.

Most of us are polyglot developers each sufficiently fluent in a couple of languages. While I see this as a strength it also means that I do not know the idiomatic solution for a task in all ecosystems in use in our projects by heart.

A few days ago I had a remote-pair-programming session with one of our customers and we wondered how to idiomatically trim certain characters from a string in JavaScript. My customer came up with the idea of asking ChatGPT for a solution while I would have asked Google or stackoverflow.

Being curious we took the ChatGPT route and it delivered a correct solution after I clarified what I mean with “trim”:

function trimCharacterFromStartAndEnd(str, char) {
  // Create a regular expression to match the specified character at the beginning and end of the string
  const regex = new RegExp(`^${char}+|${char}+$`, 'g');
  
  // Use the replace() function to remove the character from the start and end of the string
  const trimmedStr = str.replace(regex, '');
  
  return trimmedStr;
}

// Example usage
const originalString = '###Hello World!###';
const trimmedString = trimCharacterFromStartAndEnd(originalString, '#');
console.log(trimmedString); // Output: Hello World!

But from a professional perspective the code was not simple, concise and idiomatic. I intuitively knew there must be a better way.

So I did what ChatGPT does best: I chatted with it to improve the solution to arrive at a solution a was satisfied with:

function trimCharacterFromStartAndEnd(str, char) {
  return str.replace(/^${char}+|${char}+$/g, '');
}

// Example usage
const originalString = '###Hello World!###';
const trimmedString = trimCharacterFromStartAndEnd(originalString, '#');
console.log(trimmedString); // Output: Hello World!

However, you possibly need to handle regex special characters like '.', '*' etc. if they can part of your characters to trim.

Some of the intermediate steps also have their uses depending on the needed flexibility. See the full conversation at trim character from string chat.

Similarily, stackoverflow provides some comprehensive answers you can adapt to your specific situation.

Evaluation

Using ChatGPT can actually provide you useful results. To make the most out of it, you have to be able to judge the solution provided by the AI and try to push it in the wanted direction.

After my experiment our students got the inofficial advice that their solutions should not be worse than what ChatGPT delivers. 😀

Arriving at a good solution was not faster or easier than the traditional developers’ approach using Google and/or stackoverflow. Nevertheless it was more interactive, more fun and most importantly it worked.

It was a bit disappointing to lose context at some points in the conversation, with the g-flag for example. Also the “shortest” solution is longer than the variant with the regex-literal, so strictly speaking ChatGPT’s answer is wrong…

I will not radically change my style of work and jump on the AI-hype-train but I plan to continue experimenting with it every now and then.

ChatGPT and friends certainly have some potential depending on the use case but still require a competent human to judge and check the results.

The day the machines took gaming away

Just a few years ago, bots in computer games were a liability for the team. Now they are the preferred teammate. What happened?

August 5th, 2018 was a noteworthy day in the history of mankind. It was a Sunday and had Europe aching in unusual heat and drought. But more important, it was the day when the machines gently asserted their dominance in the field of gaming. It was the day when our most skilled players lost a tournament of Dota 2 against a bunch of self-learned bots.

“Bot” used to be a vilification

How did we end up in this situation? Let’s look back at what “bot” used to mean in gaming. Twenty years ago, we were thrilled about games like Starcraft where you control plenty of aggressive, but otherwise dumb units in a battle against another player that also controls plenty of those units. The resulting brawls were bloody, chaotic and ultimately overwhelming with their number of necessary tasks (so-called micromanagement) and the amount of information that needed to be processed at once to react to the opponent. In a human versus human (or pvp for player versus player) game, those battles were usually constrained to a certain area and executed with a certain laissez-faire attitude. Only the best players could stage two or more geographically independent attacks and control every unit to their full potential. We admired those players like astronauts or rockstars.

If you could not play against another human, you would start a game against a bot. A bot usually had four things that worked in their advantage and a lot of things stacked agaist them. In their favor, they had minimal delay in their reactions, ultimate precision in their commands and full information about everything on the gamefield. And more often than not, they received more game resources and other invisible cheats because they didn’t stand a chance against even moderately skilled humans otherwise. Often, their game was defined by a fixed algorithm that couldn’t adapt to human strategy and situational specifics. A very simple war of attrition was enough to defeat them if their resource supply wasn’t unlimited. They didn’t learn from their experience and didn’t cooperate, not with other bots or allied humans. These early bots relied on numbers and reaction speed to overwhelm their human counterparts. They played against our natural biological restrictions because the programmers that taught them knew about these restrictions very well.

Barely tolerated fill-ins

Those bots were so dumb and one-dimensional that playing with them against other opponents was even more of a challenge because you always had to protect them from running in the most obvious traps. They weren’t allies, they were a liability that dictated a certain game style. Everybody preferred human allies even if they made mistakes and reacted slower.

The turning point

Then, a magical thing happened. An artificial intelligence had trained itself the rules of Go, a rather simple game with only two players taking turns on a rather static gamefield. This AI played Go against itself so excessively, it mastered the game on a level that even experts could not grasp easily. In the first half of the year 2017, the machines took the game Go out of our hands and continued to play against themselves. It got so bad that an AI that was named AlphaGo Zero taught itself Go from scratch in three days and outclassed the original bot that outclassed mankind. And it seemed to play more like a human than the other bots.

So we got from dumb bots that were inferior stand-ins for real humans to overly powerful bots that even make it seem as if humans are playing in just a few years.

The present days

It should be no surprise to you anymore that on that first Sunday of August 2018, a group of bots beat our best players in Dota 2. There are a few noteworty differences to the victories in Go:

  • Dota 2 is a game where five players battle against five other players, not one versus one. It wasn’t one bot playing five characters, it was five bots cooperating with only in-game communication against humans cooperating with a speech side-channel.
  • Go is an open map game. Bot opponents see every detail of the gamefield and have the same level of information. In Dota 2, your line of sight is actually pretty limited. The bots did not see the whole gamefield and needed to reconnoiter just like their human opponents.
  • In Go, the gamefield is static if nobody changes it. In Dota 2, there a lots of units moving independently on the gamefield all the time. This fluidity of the scenario requires a lot of intuition from human players and bots alike.
  • The rules of Go are simple, but the game turns out to be complex. The rules of Dota 2 are very complex, but the game refuses to be simple, because the possibilities to combine all the special cases are endless.
  • Go is mostly about logic, while Dota 2 has an added timing aspect. Your perfect next move is only effective in a certain time window, after that, you should reconsider it.

Just a year after the machines took logic games from us (go and read about AlphaZero if you want to be depressed how fast they evolve), they have their foot in the real-time strategy sector, too. Within a few years, there is probably no computer game left without a machine player at the top of the ladder. Turns out the machines are better at leisure activities, too.

The future?

But there is a strange side-note to the story. The Go players reported that at first, the bots played like aliens. Later versions (the purely self-learned ones) had a more human-like style. In Dota 2, if you mix bots with humans in one team, the humans actually prefer the cooperation with the bots. It seems that bots could be the preferred opponent and teammate of the future. And then, it’s no longer a game of humans with a few bots as fill-in, but a game between machines, slowed down so that humans can participate and do their part – as a tolerated inferior fill-in.