← Paper Reviews

NES: An Instruction-Free, Low-Latency Next Edit Suggestion Framework Powered by Learned Historical Editing Trajectories

NES: An Instruction-Free, Low-Latency Next Edit Suggestion Framework Powered by Learned Historical Editing Trajectories, Chen et al., FSE’26

Imagine you have an LLM operating as a coding assistant. It looks at the code you’re currently writing, with a small handful of surrounding lines as context, and tries to guess what you’re going to write next. The context window is small, and the LLM is able to generate suggestions within a few tens-to-hundreds of milliseconds of latency.

This works great for some tasks! If you start writing a function definition, the name of the function alone is often enough for an LLM to infer your intent and attempt to implement the function.

What about non-code-writing tasks though? If you delete or modify a chunk of code, now you need to fix all the consumers of that code. Ideally your coding assistant would help you with all those modifications as well.

Unfortunately, the simple implementation we talked about above can’t help with these code modification tasks, because the dependencies of our altered code may lie outside the LLM’s context window. There’s an inherent tension here - an ideal coding assistant should be both fast and exhaustive. The larger we make the context window, the better the ability of the coding assistant to spot faraway changes, but the longer it will take to receive suggestions. In a larger codebase with hundreds or thousands of files, stuffing the entire codebase into context isn’t going to be feasible.

Output performance is also a problem - there’s two axes a model has to get correct - both the location the user wants to edit next, and the edit the user will want to make at that location. Generating that next edit content is expensive, and potentially useless - if the next location is predicted inaccurately, that content generation work went entirely to waste.

How can we address this? From Chen et al:

We present NES (Next Edit Suggestion), an instruction-free, low-latency code editing framework that leverages learned historical editing trajectories to implicitly capture developers’ goals and coding habits. NES features a dual-model architecture: one model predicts the next edit location and the other generates the precise code change, both without any user instruction.

Chen and co split this problem up into two separate problems, and use a dual model approach to tackle each independently. First, the ‘NES-location model’ tries to figure out where the next edit will happen. Then the ‘NES-edit model’ tries to figure out what those edits should be.

The key here is that the location model (the ‘where’ model) needs to be run continually, after every user action. The edit model (the ‘what’ model) can be delayed until after the user picks a location. This means the two models can have very different ideal characteristics:

location modeledit model
run frequencyafter every user actionon-jump
ideal context window sizelargesmall
output sizesmalllarge
latency requirementfastslow
edit history requirementyesyes
faraway diagnostics requirementyesno

The location model needs to be fast, and ideally should be able to surface next edit locations even if they’re very far away. It needs to be run continually (after every user action), and therefore needs to be cheap.

The key for the edit model is that it only runs after the user has picked a location, so is only running when the user has already strongly indicated intent. The performance requirements for the edit model are very different as a result. The context window can be shrunk, as the user has already identified the exact area they want to edit. This model is not going to be run continually, so accuracy becomes more important than speed, giving us a larger latency budget.

Implementation

It’s worth noting that this is not a novel approach. This location vs content split seems to be the initial approach taken by GitHub Copilot Next Edit Suggestions (name adopted by the authors). The big contribution of the authors here is publicly sharing details on how to make this approach successful in practice. Here’s some details that jumped out to me, though if you’re not trying to implement NES yourself this section may not be particularly useful to you.

Training Data

On the training data front, one aspect I hadn’t thought about - training the LLM when not to suggest any edits:

Relevant Edits: If the LLM filter determines that the current edit is a logical and predictable continuation of the historical trajectory, the instance is treated as a modification (-do) sample. The original ground-truth edit is retained, teaching the model that the history provides a valid basis to predict the corresponding modification or navigation.

Irrelevant Edits: Conversely, if the filter assesses the edit as uncorrelated with the history, it implies that the developer’s next action cannot be reliably predicted from the preceding edits. In this case, the instance is repurposed as a preservation (-keep) sample. This crucial step teaches the model to refrain from making a suggestion when the developer’s intent is not inferable from the available history.

Reward Function Optimization

Reward function optimization - the authors ended up creating separate reward functions for the location and edit models:

Reward Function for NES-Location Model. In contrast, the task of the NES-Location model is to predict a discrete, precise location. In this context, the concept of partial credit is less applicable. Therefore, the reward function RLocationR_{\text{Location}} is a straightforward binary signal based purely on accuracy:

RLocation(Lgen,Lgt)={1.0if Lgen=Lgt1.0otherwiseR_{\text{Location}}(L_{\text{gen}}, L_{\text{gt}}) = \begin{cases} 1.0 & \text{if } L_{\text{gen}} = L_{\text{gt}} \\ -1.0 & \text{otherwise} \end{cases}

Reward Function for NES-Edit Model. The reward function for the NES-Edit model is designed to prioritize perfect accuracy while also assigning partial credit to semantically similar, potentially useful suggestions. This is achieved through a hierarchical reward structure based on Exact Match Rate (EMR) and Edit Similarity (ES). The reward REditR_{\text{Edit}} is defined as:

REdit(Egen,Egt)={1.0if Egen=Egt0.5×ES(Egen,Egt)if ES(Egen,Egt)>0.51.0otherwiseR_{\text{Edit}}(E_{\text{gen}}, E_{\text{gt}}) = \begin{cases} 1.0 & \text{if } E_{\text{gen}} = E_{\text{gt}} \\ 0.5 \times \text{ES}(E_{\text{gen}}, E_{\text{gt}}) & \text{if } \text{ES}(E_{\text{gen}}, E_{\text{gt}}) > 0.5 \\ -1.0 & \text{otherwise} \end{cases}

A reward of 1.0 is granted for an exact match, strongly encouraging the model to pursue perfect accuracy. If the generated edit is not an exact match but is substantially similar to the ground truth (ES > 0.5), a proportional reward is assigned. The scaling factor of 0.5 ensures this partial credit is strictly less than the reward for a perfect solution, while still guiding the model to generate semantically relevant code. A penalty of -1.0 is given for suggestions that are neither correct nor sufficiently similar, preventing the model from learning to produce irrelevant outputs.

The high level idea here is that location predictions are binary - the model either predicted the location or it did not. The edit suggestions are non-binary, however - ‘accuracy’ is a spectrum. Edit Similarity is used to determine the reward function for partial matches here.

DAPO

One methodological aspect I didn’t fully understand was the discussion around SFT vs DAPO:

Model Training. To endow NES with the capability for location and code editing suggestion, we designed a two-stage training methodology. Initially, both the NES-Location and NES-Edit models undergo SFT on our large-scale historical editing datasets, enabling them to learn the fundamental patterns of code modification. Subsequently, we employ Decoupled Clip and DAPO, a reinforcement learning technique using high-quality preference data, to further refine the models. This second stage aligns their behavior more closely with real-world developer intent and utility, significantly boosting the practical value of NES…

Stage 2: Reinforcement Learning with DAPO. SFT teaches patterns, but lacks task-specific optimization. RL with DAPO refines the model by rewarding correct and accurate outputs. In the RL phase, a custom reward function evaluates generated answers (Lgen or Egen)(L_{\text{gen}}\ \text{or}\ E_{\text{gen}}) against ground truth based on format correctness and content accuracy, guiding the model toward well-formed and precise outputs…

Impact of DAPO: The DAPO-trained model tends to suggest location changes more frequently, leading to a slight drop in -keep task accuracy. However, the NES-Location model was chosen for its superior -do task performance, as location changes are more prevalent in practice.

Honestly, DAPO is new to me, and probably worth some follow-up reading. I left this paper unclear what DAPO involves and why it improved location accuracy vs using SFT alone.

Edit History

How much edit history is helpful for predicting the next edit a user is going to make? If you include too little edit history, you’re removing context from the LLM which would be useful in predicting the next edit. If you include too much edit history, however, you run the possibility of including extraneous information in a way which causes the LLM to create bad predictions.

The authors try a bunch of edit history lengths against their datasets, and decide that the best approach is…3.

Table 3 demonstrates the impact of historical context length (Max Edit History) on Qwen3-4B+SFT. A history length of 3 achieves the best balance, with 72.6% -do average accuracy and 89.4% -keep average accuracy. Short histories (e.g., 1) lack sufficient context for complex intents, while longer histories (e.g., 5+) introduce irrelevant noise, hindering accuracy.

I’m not convinced that ‘3’ is the perfect solution. This seems like a very practical-minded approach to me, but my expectation here is that over the long-term larger edit histories will be more useful, and models will learn the ability to differentiate between useful context and extraneous context on their own.

The Bitter Lesson

One of the common ideas of the zeitgeist I see at the AI application layer is ‘The Bitter Lesson’.

The bitter lesson is based on the historical observations that 1) AI researchers have often tried to build knowledge into their agents, 2) this always helps in the short term, and is personally satisfying to the researcher, but 3) in the long run it plateaus and even inhibits further progress, and 4) breakthrough progress eventually arrives by an opposing approach based on scaling computation by search and learning.

I couldn’t help thinking of this ‘bitter lesson’ when reading through this paper. There’s no doubt that this 2-phase approach (splitting locations vs edits) is effective today. But the core reason we take this 2-phase approach is that it’s necessary in order to achieve our latency goals. In today’s world, we can’t provide full-text far-edit suggestions that span a large codebase within the latency expectations of the user (Chen et al use 250ms as a goal). Splitting up the problem into two phases, location vs edit, is necessary simply to get the location model running fast enough.

But if models were faster and cheaper, would we still need this 2-phase approach to separate out location and edits?

It’s worth noting that Cursor is not splitting out location and edits, and have achieved similar levels of performance with a singular model which handles both location and content. Cursor instead tries to aggressively optimize the cost of generation. A little outdated, but lots of detail in this Lex Fridman interview with the Cursor team - specific examples include large-input-tiny-output models, speculative edits, and caching across keystrokes.

The NES approach is to say ‘divide the problem and tackle each component separately,’ or, in essence, ‘make the problem as small as possible.’ The Cursor approach, on the other hand, is ‘make the problem as big as possible’, and use every tweak we can to try to make up the difference with efficiency.

I’d bet Cursor wins on accuracy even today, and that gap is only going to grow over time.

nate willard