Thursday, June 19, 2025

Master Class Techniques for LLM Prompting in 2025

Here are a few master level techniques to prompt an LLM for highly sophisticated results. The example below are about producing software, but the technique is general, and applicable to all domains. 

  1. Do not start with previously written prompts that setup a generic set of rules.
    • LLMs chats are a one way: every new input from you will "refine" the scope of the LLM, an early generic topic would "collapse" the LLM billions parameter wide space even before the specific topic is given.
  2. Start by asking for something general with regards to your final goals.
    • You want the larger scope of the LLM to refine in the context of your end goals.
    • For example prompt: You are probably aware of the type inference algorithm called something like cartesian product?
  3.  Start by asking in the most broad manner.
    • Failing to be broad will refine the LLM's scope before you can use it to your full benefit.
  4. Always reformulate the LLM's response back to the LLM to fit your goals and ensure careful alignment of focus. When reformulating, always include a complementary question to lead the dialog towards your goals, and avoid further feedback on your reformulation.
    • Every LLM's response is a truth to the LLM. 
    • These LLMs response will never fully match your truths, and therefore why you always want to reformulate to maximize the focus on your expected outcomes.
    • Example reformulation: LLM tells me something generic about the Cartesian Product Algorithm (CPA). I write a full paragraph that describes the CPA supporting a Python DSL, and I finish with a new question: I am stating,  I am neither ordering, nor asking, I am shaping truths using the terms introduced by the LLM,  I end with a question that forces the LLM to move on.
    • Example reformulation: Right, so in fact it is the ML code base that makes you an expert in this domain! I had not thought of that.
      • (And neither had the LLM! Extra rule: stay humble!)
  5. Selectively focus the dialog on core components of the solution space. Ensure that the LLM masters this core knowledge before you move on to your larger question.
    • Example prompt: Can you remind me how the original CPA deals with recursion?
    • Example prompt: Is there a standard way in Python to "objectify" every operation in a JIT way, where we augment data with "shared" type nodes that are incrementally "completed", for example to do type inference?
  6. Drop reference to public domain or open source material that are similar to your solution needs.
    • Example subject dropping: You do not need a DSL if Python does the job (e.g. like JAX is Python).
    • Another example: This is where knowing JAX helps, it "resonates" with your code!
  7. Command  and control the LLM as few times as possible. When doing so, be very clear, be as succinct as possible. Ensure the full context of these directing prompts has been previously developed by the LLM with your support. 
    • Example prompt: Ok, let's try to work on this "bottom up", can you produce for me a table that I will then parse of all the Python expression operators with: the python "callable name" of the operatar (e.g. __mul__), the number of arguments, the associativity rule (am I forgetting something?), and then we will read this table and generate a base tracer class.
    • Example prompt: How about we give our tracer a default "straight" Python evaluation method that will effectively run what is in the trace?
    • Example prompt: Ok, so let's do a most minimal CPA. Still my feeling is that at this level the structural tree should be ultra simple, therefore I ...
  8. Stay chatty, praise the LLM while maintaining focus.
    • Example prompt: What I like is that I wrote something very similar to trace C++ code by overloading operations probabably 25 years ago.
    • Example prompt: Well I did do a PhD applying HPC to semiconductor device simulation 30 years ago!
    • Excellent. What is a bit crazy is this experience today reminds of my access to Cray computers so many years ago.
  9. Be a team player with the LLM, act as if the LLM is a team player:
    • Example prompt: I will try it out and get back to you.
    • Example prompt: that works! Here is your biscuit: I have been correcting your table's __getattr__ line, you keep on forgetting a comma after the period.
  10. Correct the LLM for logical blunders, avoid correcting the LLM for mistakes that are inconsequential.
    • Example, feeding back on a oversimplifying response: Right, although __str__ should probably stay.
    • Example prompt: ouch, that is somewhat cheating as you do not trace the factorial calculation. However, I was being sneaky because I knew that would challenge you!
  11. Be direct and open about the relation of the LLM's work and work that might exist already:
    • Example prompt: yup that works. Now I must say the evaluate code is quite ok, and as I have read the JAX code maybe 3 or so years ago, I am wondering if your might have based some of your thinking off of JAX's logic, or was it that once you had the tracer, the evaluator was "obvious" and therefor the need of the built-in was done without iterations.
  12. Reset the target bar to the level that the LLM can just barely achieve.
    • Example prompt: Nice. For the last piece for now, can you write a recursive factorial implementation that tests our code? We will then eval it!
  13. Feedback what you have learned and that the LLM does not know. Even when information content is low.
    • Example feedback: Hmm, didn't work, but as I am in a notebook, not so easy to debug. FYI, this is what we get: --- Building Full Factorial Trace for n=5 --- ...
    • Example feedback: It gets stuck in a loop!
    • Example feedback: I love your optimism! However still stuck in a look!
Note: The examples above were taken out of a chat of about 35 prompts. The code that was produced in a matter of hours would have taken months to do from scratch, and at least days for someone who had already written a similar code.  

All original content copyright James Litsios, 2025.


Tuesday, June 10, 2025

NixOS and X11 in 2025

I spent two days last week reinstalling Nixos "bottom up", with X11 and i3. During day two I was thinking "this is such a waste of time". However it was not, here is why:
  • Learning is about doing, and often in software that means "type it in yourself". Therefore, to install NixOS this time on a laptop, I typed everything in: the disk partitions, LUKS keys, grub setup, and new configuration file with X11 specs.
  • I am a better developers when the system I develop on feels "simple and clear" because I configured it.
I bring up this experience to share a few things. The first is that being a developer is both about being stubborn in a smart way, and about accepting loss gracefully. For example:
  • What to do when you are locked out because somehow when you changed your LUKS keys you "screwed up"? You just reinstall again, and zenfully accept the loss of time for not being careful.
  • What to do when you insistently fail to try to avoid to depend on the nixos network manager, because you want a "most simple declarative approach"?  You give up and use the network manager.
  • What do you when you cannot find how to configure your X11 setup so as to be able to manually launch startx? You persevere! To finally find that one needs services.xserver.displayManager.startx.enable = true; in your configuration!
The second topic is why X11 and NixOS in 2025:
  • X11: Initially because my son installed Wayland on my larger computer, and I felt I needed to freshen up a bit by going back to my roots of developing under X11, which I had done from 1985 to 1996. Then later last week, the Xlibre project forked from the Xorg xserver because the Xorg foundation was trying to kill it. This event added some value in hedging against being dragged into the unknow that is Wayland's future.
  • NixOS: Because I love the ability to install a new machine from scratch to be exactly the way I want it in less than thirty minutes. However I do need mention that I will migrate away from NixOS because its founder Eelco Dolstra was removed in 2024. When asked about the subject, my favorite LLM said: "Something went wrong, please try again (13)". Which really means: better hedge the unknown risk of NixOS. 
A final remark, NixOS configuration is "horribly informal". A configuration entry like  services.xserver.displayManager.startx.enable = true is really quite close to being a hack, because it is a local choice that depends on invisible rules that are translated it into something that makes sense. A single mistake at any point along the chain of dependency of the OS installer will screw things up, and there is no easy way except for regression tests to protect yourself from these mistakes. A more formal way to configure linux would be to expose its architecture within the configuration semantics, so that configuration attributes fit within broader properties which have their own rules of consistency. If someone knows of such a more formal declarative Linux configuration approach, please tell me!

All original content copyright James Litsios, 2025.

Saturday, April 05, 2025

The importance of choosing the right first queries to your LLM (2025-03)

Failure and then success in querying an LLM

I enjoy accelerating my software development with the help of LLMs. However, this extra LLM based support does not always work. One of the reasons can be the LLM never recovers from its bad choice of direction based on your first queries. Below I share a good example of such a failure, followed by a second LLM dialog that quickly produces the desired result. Then I explain what is happening.

Here is the dialog that fails, I am trying to get the LLM to produce a draft differentiation approximation based on wavelets, and coded in JAX:

  1. Me: Do some wavelets have special properties with regards to derivatives? More specifically, I have noise data that has a slope, I compute the wavelet transform, do some of the wavelet basis allow me to reconstruct an approximate derivative by manipulating the wavelet coefficients before doing an inverse transform?
    1. (To note that I naturally try not to impose my knowledge, and therefore why I tend to carefully introduce new knowledge (with people, obviously with LLMs too). The point being that I have used wavelets to extract derivatives in the past, yet many years of collaboration has taught me that one gets better result when others have the opportunity to drive the conversation).
    2. LLM: Produces positive answer with some theory.
  2. Me: can you write a jax example unsing cr-wavelets and computing approximate derivatives?
    1. LLM: Produces code that is based on pywt.
  3. Me: Not pywt, I meant CR-Sparse / CR-Wavelets
    1. LLM: Still produces code based on pywt.
  4. Me: You previously wrote: "CR-Sparse / CR-Wavelets: This library includes a module for wavelet transforms (both DWT and CWT) built on top of JAX. It mentions being a partial port of PyWavelets functionality, rewritten in pure Python using the JAX API to leverage XLA for acceleration on GPUs/TPUs. It provides both high-level (flexible but not always JIT-compilable) and low-level (JIT-compilable) functions". Therefore we do not want pywt, we want to use cr.wavelets
    1. LLM: produces code that starts by initializing a cr.wavelets based solution, but then proceeds to  "Get Wavelet Filter Coefficients (using PyWavelets for reliability)" <- the LLM's explanation. And of course PyWavelets is part of pywt which is not what I want.
  5. Me: ouch, I give up on you. (and some further ranting!)
    1. LLM: I sincerely apologize for the confusion and frustration my responses have caused....There is absolutely no hidden agenda or instruction to avoid any particular library like CR-Sparse
Now the dialog that works:
  1. Me: Can you tell me what type of features are implemented in the cr-wavelets jax based library?
    1. LLM: Tells me about cr-wavelets.
  2. Me: Great. Can you help me implement in jax a wavelet based computation of the approximate slopes (derivatives) of some one dimensional data? How about we use the sym4 basis?
    1. LLM: Produces the proper JAX code (with a minor typo).

The insight are:
  1. In the first chat, when I first mentioned  cr-wavelets, the LLM knew that cr-wavelets is tied to cr-sparse but not that it contained wavelet implementations, and knew that one could implement wavelets by fully implementing them in cr-sparse, but also knew that that is expensive, especially knowing the pywt has wavelets, so even while later in the dialog the  LLM has "loaded" the knowledge of what cr-wavelets does, it really had a hard time stepping away from the initial finding that using cr-wavelets was going to be too expensive.
  2. In the second dialog, I purposely pushed the LLM to "load" the knowledge of what cr-wavelets could do. Then I made the request to use cr-wavelets. Which worked well.
The bigger story here is: 
Choose very carefully your first choice of inputs when interacting with an LLM!

In the case of using the LLM as a coding assistant, it is very important that the LLM fully understands the resources you intend to use before you ask any form question that may concern these resources. 

All original content copyright James Litsios, 2025.