Skip to content
aiR

Solving Problems with LLMs

Visruth Srimath Kandali
Oct 19, 20267 min read

hen working with LLMs—and in general—it is useful to think of the nature of the problem you are working on. I have encountered, and worked on, problems which broadly fit into three categories:

  1. Known design, known solution
  2. Known design, unknown solution
  3. Unknown design, unknown solution

The first set are questions where I am using the LLM to type things for me. Here, I’m expanding the idea of “knowing a solution” to also include the class of problems where I do not know the syntax but know where to look, e.g. changing a known-to-exist-but-name-unknown argument to a function (see, e.g., a previous post where I ran into this class of problem when making a plot.1). This class of problems is, therefore, known to be solvable, so an intended solution is recoverable. You may wonder why it would be useful to use an LLM for this, given that we are presupposing the solutions to be “within reach”, so to speak, and there are a few clear reasons. One, LLMs write code faster than me. Two, LLMs type code while I can do other things. Three, LLMs2 (in a proper, tight feedback loop—which is table stakes!) can smooth out the bumpy journey between “I have a conception of a solution”, and “here is a solution”.

I have merged a lot of PRs which are like this across Stan R packages, where I know almost exactly what I want but I don’t want to search documentation to find the exact thing to change, or type the code out3 since these are usually one-off changes which involve learning something specific about a specific API. That is, in these scenarios, I am deliberately eschewing fuller knowledge for time.

The second set of questions is more interesting and where I get the most use from LLMs: these are problems where I know what I want in terms of the program, but I don’t know exactly how to type it out. The key distinction between this and the last problem is that I don’t have much in the way of inductive biases about how the code should look, just how the problem should be solved. For a concrete example, I recently worked on a PR⁠ to make CmdStanR’s tests run in parallel. There were some technical limitations which I won’t bore you with directly, but the main thing I had solved up front was to mimic “copy-on-write” semantics, so that multiple workers could share as much as possible to minimize unnecessary duplication of work and to maximize throughput. I didn’t give any thought to the actual code needed to do this though; I knew what the solution should look like in terms of files touched, size of diff, etc. However, I did think about the design a good bit. The model suggested a shared model cache initially and I told it to do what it pleased for a bit as I went out or to bed or read a book. I only nudged it a little here or there—it initially wrote out some massive junk to get locking semantics and some other sprawl to check for running processes so I told it to use ps and filelock and it promptly deleted most of the cruft (see also What requirements don’t you have?⁠). Eventually I read it over and made a few small changes. The PR is pretty clean and approximately halves test times, which is pretty good for something I barely thought about.

This last class of questions is far closer to “vibecoding”, I think, though without the pejorative. These are times when I just have a problem and want it solved. LLM solutions to these types of problems are the best when the problems are easy to verify.

If you have a clear measure of success—ideally one which the LLM itself finds clear—LLMs can hillclimb. Even if an LLM can’t automatically validate a solution, just having a means to verify one is good and makes it easier to catch errors. Tasks with clear conceptions of success which can also be checked visually/quickly tighten the loop when you’re in it, and are prime LLM problems. The recent spurt of game decompilations are members of this larger set, which also includes porting or optimizing software. Problems with an oracle4 solution have become very easy to solve now (see also There’s no reason for software to be slow anymore⁠). Of course, the most important thing to note in this paradigm is that however you verify a solution must itself be verified, to ensure it captures all pertinent qualities lest you get a Goodharted solution which passes your tests but isn’t valuable.

With that in mind, we can turn back to the last set of problems; I think LLM solutions to these are dangerous, but I think there are plenty of times when that doesn’t matter. For example, this website’s theming was forked from astro-erudite⁠ around v1.6.3 and subsequently has had major changes which have been handled exclusively by LLMs, and a wide variety at that. At a high level, there are some things I conscientiously designed—I dislike client-side JS and large sites and know a little bit about some best principles to further those precepts—but I also just ask the LLM to do things and check that they work. For example, my different collections (blog, reviews, etc.); removing buttons; swapping to my personal brand colours and adding a justification library; and so on.

As a result of all this, I can guarantee my website codebase is awful (prime example: my site content and styling are tightly linked so I can’t point you to my source code), that is, I’m sure there’s some nonsense duplication, magic numbers, poorly architected systems, etc. but I don’t care since it’s a static personal site and I can eat the tech debt for fast, thinking-less changes. Again though, that is a tradeoff and here it is a much larger one. I am a computational statistician so front-end is not my livelihood; I can afford both economically and intellectually to not learn much about building a website or Astro or TypeScript; but that is a definite decision I make and compound every time I tell an LLM to go do the next thing instead of trying to figure out what that would look like or writing that code myself. That is, it is fine to eschew Naur⁠.

This last category covers a lot of things that would be nice but I would never spend the time to do: things like resurrecting/overhauling my Neovim configuration⁠, or using more nix⁠, or writing random nushell utilities, or building some cool Quarto⁠ extensions⁠, and solving many more little niggling things and building many more small projects because you can, in fact, just do things⁠ now (and have been pretty reliably with access to a frontier model for the past year!)

But that doesn’t mean you can or should—I have been meaning to write a little daemon to sync my Zotero files to my Kindle via Gmail, but I haven’t gotten an LLM to write it because I want to write it; I want to write it in OCaml and eventually OxCaml and optimize it and put out something that is probably (maybe even provably) suboptimal and rough and human—because I want to learn. And that is fine, for artisanal software, which holds mostly prescribed value; but more and more untenable for “real” software, outside of the special cases where the models are still bad at writing code like they used to be in most of 2024 (depending on the problem and the language).

In essence, ineffable taste⁠ is still critical, but beyond “taste” basic engineering/design is critical as the models keep writing as you keep thinking (see also, There’s no point at which turning your brain off will work⁠; Automatic programming⁠). Most importantly, you need to think hard about what you should be thinking about.

Footnotes

  1. I pasted just the problem image with the prompt “I need to remove the grey background behind each line in the legend using ggplot how” and GPT-6 Sol on High in webchat correctly identified the solution (“The grey rectangles in your legend likely come from geom_ribbon(). Add show.legend = FALSE to that layer”). I didn’t have the “using ggplot” bit at first and it started using its image editing tool so I added that. Things have changed a lot since last August. ↩︎

  2. “LLM” in this post should be understood as “frontier LLM”, the modern models are much better than the old ones. See footnote 1 and that linked post for an oblique example, or myriad other posts online—the typical inflection point I’ve heard is late 2025, Novemberish. ↩︎

  3. Even though I type pretty fast! Permit a boast, or a presentation of my bona fides: my 100-word WPM on Monkeytype is usually around 120, 98% accuracy; my 15-second sits at 150, 99% accuracy. ↩︎

  4. hopefully lowercase O. ↩︎

Did you enjoy this article?

Recommend it — Standard Reader surfaces well-loved writing to more readers across the network.

Across the AtmosphereDiscussions