logoalt Hacker News

colingauvintoday at 2:25 PM1 replyview on HN

>Run the same exact prompt 100x in a single step test (one prompt, one response), hash the full responses, and you’ll see 10-50+ unique responses. The higher the unique the worse your prompt; focus on the system. A highly tuned system prompt will result in one response, even at a temperature of 1.0. Really. Once that’s done that’s the only thing it does and it’s the only one that does it and it never changes. Other LLMs that call ‘check_email()’ are unknowingly just passing a prompt to the specialized one.

This is a brilliant idea, thank you. Convergence as a metric for prompt robustness.


Replies

docjaytoday at 4:07 PM

No problem. That’s where I spend a solid 98% of my time because it’s worth it, and I can show the measurements.

Couple tips:

A first pass is to blank out the system prompt, add only one tool, and work to reduce the thinking length for a direct function call prompt. “Read archive.log” should result in roughly 0 length thinking. If it’s thinking about anything, especially if it mentions {readfile tool}, rename the tool and minimize the description. Depending on the model it might always output thinking, so run it until you get a consistent outlier that’s far lower thinking length than the others. It’ll be obvious when you find it. Repeat the prompt dozens of times, modify it slightly, and focus on the lowest max length, not average.

You should really use a Claude with Python (or similar preferred) to make API calls to the LLM and have it iterate through hundreds of names/descriptions and return only len(thinking). Have it build a batch testing harness to run a dozen tests at a time, that helps keep it from ‘cheating’ to finish. laziness = count(messages), but frame it as an academic research project studying the effects of minimalist tool descriptions on thinking length. Don’t set the goal as minimal thinking length, Claude will short circuit it.

Remove all other tools until {readfile} is perfected, then add/test the next tool. Btw: you don’t need to describe readfile() when it’s named right.

The built-in tools[] makes that hard because it tacks a really dumb system prompt on at the server and requires some length of description, which is why I built my own function calling, but that’s still a good first pass. Focus almost entirely on the function name itself; readfile, readFile, read_file, readlines, file_get_contents, etc., and make the description just “Operational” or similar. Field description, if required by API, is literal “filepath”, same as field itself. Lowercase, nothing else said. Minimize your contribution to perplexity, use standard naming conventions.

When you add a second tool you need to still include the first tool prompt in the second tool testing. Adding {writefile} can absolutely break {readfile}. Have Claude run the tests and build it out into permanent testing module with file_read=[prompts], file_write=[prompts], making it easy to extend, and full_test() that runs them all to see if a new addition broke it.

Add your system prompt back in and probably watch the tests go to shit. <- THAT is likely your biggest problem. My system prompt for the main LLM has all of the tools it can use, which is ~30 lines of function names with no call syntax, and yet it has more tools than Claude Code and never messes them up.

Start with nothing and slowly work up. Focus on positive action framing, not negating: “Your responses are always..” and not “Do not…”

It sounds like a pain, but building the systems to automate the tests IS the infrastructure, everything you have it do afterwards is just the tasks.

That was longer than I planned, but I guess this’ll be a comment for future generations to find.