惯性聚合 高效追踪和阅读你感兴趣的博客、新闻、科技资讯
阅读原文 在惯性聚合中打开

推荐订阅源

Hugging Face - Blog
Hugging Face - Blog
B
Blog
博客园_首页
OSCHINA 社区最新新闻
OSCHINA 社区最新新闻
G
GRAHAM CLULEY
Microsoft Azure Blog
Microsoft Azure Blog
让小产品的独立变现更简单 - ezindie.com
让小产品的独立变现更简单 - ezindie.com
WordPress大学
WordPress大学
The GitHub Blog
The GitHub Blog
Security Latest
Security Latest
F
Full Disclosure
云风的 BLOG
云风的 BLOG
freeCodeCamp Programming Tutorials: Python, JavaScript, Git & More
C
Cyber Attacks, Cyber Crime and Cyber Security
L
LINUX DO - 热门话题
V
Visual Studio Blog
有赞技术团队
有赞技术团队
腾讯CDC
V
V2EX
Vercel News
Vercel News
C
Cisco Blogs
V2EX - 技术
V2EX - 技术
Scott Helme
Scott Helme
K
KPMG report finds enterprise disconnect between AI and its ROI | CIO
AWS News Blog
AWS News Blog
S
Schneier on Security
Exploit-DB.com RSS Feed
Exploit-DB.com RSS Feed
小众软件
小众软件
G
Google Developers Blog
C
Check Point Blog
C
CERT Recently Published Vulnerability Notes
博客园 - 叶小钗
S
SegmentFault 最新的问题
T
Tor Project blog
J
Java Code Geeks
L
Lohrmann on Cybersecurity
Application and Cybersecurity Blog
Application and Cybersecurity Blog
T
The Exploit Database - CXSecurity.com
Apple Machine Learning Research
Apple Machine Learning Research
T
Tailwind CSS Blog
H
Hackread – Cybersecurity News, Data Breaches, AI and More
博客园 - 司徒正美
钛媒体:引领未来商业与生活新知
钛媒体:引领未来商业与生活新知
S
Secure Thoughts
量子位
N
News and Events Feed by Topic
MyScale Blog
MyScale Blog
TaoSecurity Blog
TaoSecurity Blog
奇客Solidot–传递最新科技情报
奇客Solidot–传递最新科技情报
Engineering at Meta
Engineering at Meta

Pierce Freeman

A browser for agents | Pierce Freeman The grey market of podcast appearances The way I travel | Pierce Freeman Fixing slow AWS uploads | Pierce Freeman Local tools should still use vaults We solved scratch content first Starting a podcast in 2025 Being late but still being early Automating our home video imports Adding my parents to tailscale A deep dive on agent sandboxes Language servers for AI | Pierce Freeman My simple home podcast studio We need centralized infrastructure | Pierce Freeman Coercing agents to follow conventions using AST validation My unified theory of social selling My personal backup strategy | Pierce Freeman July updates to the homelab How the KV Cache works httpx is the right way to do web requests in Python Reputation is becoming everything | Pierce Freeman Building a (kind of) invisible mac app Updated knowledge in language models Making an ascii animation | Pierce Freeman How speculative decoding works | Pierce Freeman Under the hood of Claude Code Doing things because they're easy, not hard Speeding up sideeffects with JIT in mountaineer Firehot for hot reloading in Python Misadventures in Python hot reloading How text diffusion works | Pierce Freeman The ergonomics of rails | Pierce Freeman How language servers work | Pierce Freeman Just add eggs | Pierce Freeman Unfortunately SEO still matters | Pierce Freeman The futility of human-only web requirements Setting up Input Leap | Pierce Freeman Checking in on Waymo | Pierce Freeman The react revolution | Pierce Freeman Speeding up many small transfers to a unifi nas Quick notes on swift libraries AI engineering is a different animal San Francisco | Pierce Freeman Debugging a mountaineer rendering segfault Local network config on macOS Building our home network | Pierce Freeman Introducing Envelope.dev | Pierce Freeman Legacy code and AI copilots Typehinting from day-zero | Pierce Freeman Generating database migrations with acyclic graphs Lofoten | Pierce Freeman Mountaineer v0.1: Webapps in Python and React Constraining LLM Outputs | Pierce Freeman Passthrough above all | Pierce Freeman Accuracy in kudos | Pierce Freeman How quick we are to adapt The curious case of LM repetition Costa Rica | Pierce Freeman Debugging chrome extensions with system-level logging Speeding up runpod | Pierce Freeman Inline footnotes with html templates Parsing Common Crawl in a day for $60 An era of rich CLI All or nothing with remote work The Next 10 Years | Pierce Freeman Adding wheels to flash-attention | Pierce Freeman LLMs as interdisciplinary agents | Pierce Freeman New Zealand | Pierce Freeman Representations in autoregressive models | Pierce Freeman Let's talk about Siri | Pierce Freeman Minimum viable public infrastructure | Pierce Freeman Reasoning vs. Memorization in LLMs Automatically migrate enums in alembic Greater sequence lengths will set us free On learning to ski | Pierce Freeman Dolomites | Pierce Freeman Using grpc with node and typescript Opportunity years | Pierce Freeman Buzzword peaks and valleys | Pierce Freeman Buenos Aires | Pierce Freeman Network routing interaction on MacOS Independent work: November recap | Pierce Freeman Debugging slow pytorch training performance The provenance of copy and paste Debugging tips for neural network training Patagonia | Pierce Freeman Santiago | Pierce Freeman My 2022 digital travel kit AWS vs GCP - GPU Availability V2 Independent work: October recap | Pierce Freeman Planning Patagonia | Pierce Freeman Relationship modeling | Pierce Freeman The power of status updates A new chapter | Pierce Freeman Give my library a coffee shop AWS vs GCP - GPU Availability V1 Switzerland | Pierce Freeman Headfull browsers beat headless | Pierce Freeman Webcrawling tradeoffs | Pierce Freeman Copenhagen | Pierce Freeman
The tenacity of modern LLMs
2025-06-21 · via Pierce Freeman

If you compare the raw benchmarks for Claude 4 Sonnet vs 3.7, we see solid gains but not a huge relative difference. AIME improved from 80% to 85%1. MMLU climbed to around 86.5% from 86.1%. The SWE-bench score jumped from 70.3 to 80.2%.

But like all metrics, those don't tell the whole story.

What I've been surprised to experience is the tenacity of modern LLMs. Give them a scoped task with some provable success criteria (ie. unit tests) and these models will keep iterating until they find a solution. Even if that means burning through a ton of context or reasoning tokens to get there.

My approach to kicking off these async runs is pretty straightforward. Here's the template of my usual prompt with some color commentary.


my problem is abc. This will mostly affect @file1 and @file2.

Establish the specific goal that should be accomplished and the file targets that are jumping off points. For net-new logic that doesn't tie to an existing file I usually still guide it to some files that I know to be relevant.

I'm not too rigorous about providing this project specification. I usually describe the feature/bug, my pre-existing knowledge of what I think is going on and how I would solve it, and how it would affect the user (if it's a frontend feature). I haven't found the approach of creating a PRD to be particularly helpful to improving the outcome, aside from making you formalize your thinking about what's in scope.

make sure to follow the context that's already provided to you about the codebase. start by researching the current state of affairs in this code by recalling the most relevant files for this refactor.

Even with our initial files, the model still needs to warm up its internal state about how these files relate to the rest of the codebase and where we might need to make changes.

But having a starting place with these files is helpful to more specifically compose RAG searches. It has the additional context of the headers and classes that might be imported in other files.

let's first write a stub version of the logic. this should implement the core functionality (correct function signatures, class definitions, and dataclasses).

then first write a simple happy path unit test that tests this new flow

As much as possible we're trying to follow a TDD pattern here. But in a conventional TDD setting we'd usually sketch out the full API contract on paper first before we write the test, to make sure that the unit test is really baked before we start writing the code. But in practice I've found that the models are better at outputting first-draft code than deriving the right API contract without the code. So we cheat a little here and code a draft before we do an initial unit test, to get a sense for the scope of the happy path test.

once that is done, run the test and iterate on the code until it executes properly.

Run an initial version of the test to get the feedback, then instruct the model to perform a loop until it's solved. Behind the scenes these agentic settings let the model choose if it should continue processing the next message2, so we need to indicate that it should always be making changes concurrent with running the tests. The tests inject more information into the system that can be used to write the subsequent message. Without a specific instruction to loop itself the model sometimes won't and just bail out early.

every time you make a change, sanity check your changes by running uv run pytest -vvv -k {new unit test}. only when you're done with the full refactor should you run the unit tests on the entire codebase.

Focus just on making the current test pass, mostly for speed of iteration but also for overall focus of the task. When we have this scoped logic complete we can then zoom out and make sure we didn't break other areas of the test. Scoping also helps avoid a lot of model verbosity, like if you've ever experienced the model liberally modifying/creating files that are just clearly not relevant to the core task.


Certainly a prompt like this won't work all the time but it does a solid first pass most of the time (especially for webapp development or targeted data processing jobs). I'm working on a Swift project right now and this was the loop that it followed for a recent feature:

  • Read 3 other swift files
  • Update todos
  • Update files (x6 changes): initial implementation of NSData.decompressed
  • Run build
  • Build fails because of syntax (missing enum)
  • Updates files (x1 change): update syntax
  • Run build
  • Build fails because .gzip isn't available in the NSData compression API
  • Update files (x1 change): Implement a proper gzip decompression using the Compression framework
  • Run build
  • Build fails because it was trying to use a zlib wrapper instead of gzip
  • Updates files (x2 change): Switch to /usr/bin/gunzip via an external Process
  • Run build
  • Build successful

It tried three wholly different approaches here: one with NSData, one with the Compression APIs, and one with an external executable bundled with macOS. This comes back to tenacity.

Tenacity requires a feedback loop. And coding happens to be one of the few domains where that feedback can be nearly instantaneous. Write some code, run it, see what breaks, fix it, repeat. When you give an LLM access to this loop (whether through unit tests, script output, or webapp console logs) it's able to acquire more context that drives the next step. If the method call is failing, check the signature. If an edge case is failing, consider more complete handling.

There's something that feels very information-theoretic about this setting. You're injecting more information into the closed-system without having to do anything yourself. But since you're injecting information into the system, you can still run into the same garbage-in-garbage-out problem that plagues all language models.

Unit tests have provided my most reliable guardrail on agent behavior. Since after all, when a model manages to make them pass, you get both working functionality and a regression test for future changes. Agents are way too willing to spam you with unit tests if left to their own writing, however, so making sure the happy path is stable before adding additional coverage has been the best way I've found to avoid code slop.

There seem to be some common approaches to how LLMs usually go about debugging. There's nothing empirical about this analysis but casual observations from extensive usage over the last month:

  1. Get the code running first. If something won't compile or execute after several attempts with minor fixes, the model will often step back and try a different approach entirely—maybe switching libraries or reframing the problem.

  2. When logic fails, simplify. I've seen models struggle with complex regex patterns for text parsing, fail repeatedly, then suddenly pivot to writing explicit parsing logic with for loops and string operations. Less elegant, perhaps, but I suspect clearer logic about how it works. This itself I find quite interesting: since regexes are a formal language, you would think that a machine would be quite efficient at writing them. But much like how LLMs often fail at math, my guess is reasoning through the full internal state of what a state-machine would do given a regex pattern is just too complicated. Loops are more explicit.

  3. Fallback to bash If RAG searches aren't returning the expected context, the models are pretty liberal at using a bash terminal to navigate the disk hierarchy (cd, ls) and inspect files manually (head, cat). This helps in contexts where dependency files are not otherwise mapped as part of the project. But I've also seen it quite a bit in "trying" code syntax to make sure it passes in a more isolated environment.

  4. Liberal Prints There's definitely an MCP server out there that can set breakpoints in running code, but it doesn't seem like the current generation of architectures are particularly optimized to stepping through stack traces. My hunch is it requires a bit too much concurrent context that models aren't optimized for in their turn-based setting: the full stack, the current breakpoint, the suite of variables.3 Instead, models prefer to add a lot of print statements as their way of postfacto stepping through the behavior of the executing code and making changes based on it.

At the risk of anthropomorphizing these models too much, we've definitely RLHF'd our way to a workflow that mirrors what people do. There's something almost human about watching a model work through a hard problem: the false starts, the gradual understanding, the moment when the pieces finally click together. Even if this isn't reasoning in the conventional sense, it wouldn't surprise me if the workflow of a lot of software development can be brute-forced by just injecting ever increasing context into the system. You're converging on the right code by trying different things.

If you squint, there's some deeper link between software development and gradient descent. You start at an initial parameter space (your code), you make some step (modify a file), you run a forward pass (try to run unit tests), and apply the backward gradients (make a new modification that tries to fix the code). It just so happened that humans were approximating this behavior with Stack Overflow and setting breakpoints. Models have their own strategy of doing that same thing.

There's a cliche loved by coaches and teachers. Hard work beats talent when talent doesn't work hard. At least in the case of language models, the talent is certainly willing to work pretty damn hard.

We'll see how far that gets them.

  1. Not an exact comparison because 3.7 was benchmarked on the 2024 edition of the dataset and 4.0 was benchmarked on 2025. ↩

  2. This itself is a bit of a simplification. Since the models are just being called by client callers in an infinite loop, what we're really looking for is the model to output a message with no more tool calls (or an empty text context). At this point we have no more information to inject into the model, so we break out of the loop. ↩

  3. Past a certain context length, all IDEs (Claude Code, Cursor, etc) will truncate your message history to avoid reaching the actual limit of the inference model. Some do it explicitly. Others more opaquely transform your past messages into RAG structs and then just query for the most relevant ones when the next message comes in. My hunch is the RAG approach is more flexible but there's certainly something appealing with the simplicity of the single shot summarization approach. ↩