Why people suck at using LLMs

Why people suck at using LLMs   ai

Note: This is an off-the-cuff dump of thoughts.

I was talking to my dad (software engineer with 30 years of experience, currently working on a startup that encourages LLM use. Big fan of LLMs) about this last night and I think there's like sort of three reasons that people tend to have bad experiences with LLMs, usually one or more of them.

Problem one: people don't know how to quickly and concisely conceptualize and express what they want

They tend to only be able to even conceptualize what the heck they're even trying to do in the process of banging out the low level code to do it, and even then only gradually and by constantly ricocheting between errors and compiler failures to help guide them.

If you ask them to explain in English what they want, they don't know what the right level of abstraction is to explain it at. And even if they do, they just struggle for minutes at a time trying to figure out what to say and then how to phrase it and type it in. This makes them often feel like just directly coding is faster.

For instance, for me expressing even a fairly complicated set of dynamic programming algorithms and the data structures that they use for a particular domain is like a maybe 20 second thing at most, once I've come up with the idea because the natural language description of what I want is what I have in my head beforehand and I generally do always have an idea of how I want to implement things before I go about implementing them and rarely run into runtime or compiler errors with my overall plan of implementation ever in the process of implementing unless it's a stupid silly mistake like swapping the order of the arguments of some API. The flexibility of natural language is actually an advantage for me because I generally know exactly what the relevant level of abstraction is for each component of whatever I'm planning to do in terms of how to express it. So I don't spend a ton of my time essentially writing out pseudocode nor do I write something that's so vague in general that the AI doesn't know what I mean.

This isn't some kind of superpower. It's just decades of practice writing and reading philosophy and other areas where you're expressing complex ideas in a way that needs to be at the right level of abstraction and as precise as it needs to be without being too precise. It's something that you can absolutely learn, but given how notoriously terrible most developers are at writing documentation or technical writing in general, it should be obvious that most of them haven't bothered to learn this skill. And so, of course, they suck at it and then blame the tools for it.

Problem two: they go in expecting too much, usually in bad faith

So they give it like a four-word prompt and expect it to invent the next operating system kernel in one shot and then complain when the architecture is bad and wrong and the code is not good quality and the overall thing doesn't work very well.

If people explain to them that they need to actually specify what they want, then we go back to problem one: they feel like specifying what they want is impossible; or, they turn the conversation to problem three…

Problem three: they don't know how to actually plan anything out, or are ideologically opposed to it

Usually, you get the best results out of LLMs if, instead of immediately trying to dive into implementation with no plan or context, you actually try to take some hammock time and figure out what it is you really want and how you want to achieve it.

Generally, this involves having a conversation with the LLM in plan mode — without ever writing some any code — where you discuss your intended features, design philosophy, and goals, and then the architecture, data structures, algorithms, data flow, concurrency model, and other system engineering considerations that you want to use to achieve those goals; then once that's completed, come up with a phased plan for implementation.

Then you have the LLM right out a structured specification document and set of behavior-driven development and to end feature tests for what you want, so that you have this plan to refer to both for yourself and the LLM in the future to maintain consistency and declare understanding of what you're doing and where you're going, as well as an automated executable specification to validate where you are in relation to where you want to be.

This doesn't just work for wholesale greenfield projects either. This is generally a good way to approach building specific features within larger projects as well. It's just that in this case, first you spend a session building up documentation about how the existing code base works and what it does and what its style and approach is and what the relevant files and functions and so on are. Once you've built that up then you spend a second session doing the planning and write a specification just for the particular feature you're looking for.

(Note that this intermediary first step of learning the existing code dates is actually not optional, even if you're in a project with substantial documentation, even if that documentation is designed for agents, because you yourself need to understand how the project works and where things are in order to come up with a good specification for the feature you intend!)

A lot of developers seem to have problems with this, both because they have problems actually understanding what they want to do and how they want to go about it before they start just bumbling around in the source code (see problem one), but also because there seems to be some kind of ideological opposition to it based on the sort of collective intergenerational scar tissue, the software engineering community has developed around the Waterfall method.

However, I think this approach is meaningfully different from Waterfall, because the specification isn't immutable: It isn't handed down from management or some consulting company or from users or customers or the government or anything. It isn't even a finished artifact produced in an earlier phase of a fixed production pipeline. It is a local, living, non-binding document that you are free to evolve, change, and improve as your ideas develop or technical constraints rear their head. It's just giving you a place both beneficial to yourself and the agents you are using to form some consistent, clear reference point for what you're trying to do and the design you're trying to achieve. And the planning stage before you begin at all just gives you a chance to get your initial direction and goals clear in your head before you jump up and run off into the jungle.

Problem Four: pride lmao

Whenever you bring up any one of the three previous problems to anyone who is loudly proclaiming from the rooftops that they've had a bad experience with AI, the typical response is a very common thought-terminating cliche: "oh, so I'm holding it wrong?"

The answer to this, of course, is yes, but the specific phrasing is meant to make it impossible to actually respond in the positive because it's a reference to a notorious instance where Apple released an obviously defective product, a phone with a poorly designed antenna, and then released a condescending advertisement telling people that there wasn't a problem with the phones antenna, it was just that they were holding the phone wrong; when, in fact, the way people were holding phones that was causing the antenna to drop a signal was literally just the normal and obvious way to hold the phone.

The obvious implication being that anyone telling people that they are using LLMs wrong, or haven't built up the proper skills to use them productively, is just a condescending idiot defending a fundamentally defective product.

The problem is that LLM coding agents are not a consumer product: they're not designed to be a technology remotely as widely used by the general population, with established and understood modes of use, as a smartphone. There I high power tool directly targeted at software engineers. Some tech CEO's may claim that eventually soon, sometimes soon, AI will replace software engineers, but that doesn't mean that coding agents themselves are designed to do that, and random things CEOs say to pump their bubble don't actually change the nature of what their product actually is; the entire point of actually exploring and using these tools is to figure out what they're actually useful for and how they actually work, apart from all of the hype. I would have expected AI skeptics to agree with this, but it seems that their position is different: that if it doesn't live up to the wildest hype that people like Dario Amodei put out, then it must be completely and utterly worthless. So if Dario Amodei insists that you shouldn't need any software engineering skill to use these things, then AI skeptics shouldn't have to learn any skills to use these things at all.

I think this is a fundamentally disingenuous and unhelpful way to approach the problem. It's a way of approaching the problem designed to set these tools up for failure, in order to then provide the skeptic with more ammunition to lob at people that like me that actually find the tools useful, to insist that all of us are addicts or falling for persuasion tricks alone. I think someone genuinely approaching with an open mind and trying to understand whether these things are useful or not would actually be open to the idea that there may be skills that they may have to learn or exercise more or different workflows they may need to try in order to get productivity gains out of these tools. Just like literally every software development tool before.

And that's the thing, right? These are powerful and productivity enhancing and cognitive load reducing software engineering tools. But just like compilers or type systems or new languages or new concurrency models or new editors or new IDEs or new testing frameworks, they require being learned and understood in order to gain productivity. And while you're still having skill issues with them, or getting used to them or adapting your workflow to them, you'll see a productivity decrease and it will take effort in order to get what you need out of them. Would it be valid to lob the you're holding it wrong, phrase at someone insisting that if you want to see the most benefit out of VIM or Emacs, you should actually learn their key bindings?

Or that if you want to see the benefits of strong static type systems (say, in the ML family), you actually have to learn how to do type first development and model your domains with them?

Or to say that if you want to see the most benefits out of Lisp, you actually have to learn and practice to use its abstractions?

Or that if you want to see benefits out of functional programming, you need to learn how to think with it?

Or if you want to see benefits from testing that you need to modify your workflow?

No.