Enhancing Knowledge Density via Hierarchical Context Pruning for Retrieval-Augmented Repository-Level Code Completion
Organizations: MIIT Key Laboratory of Pattern Analysis and Machine Intelligence, College of Computer Science and Technology, Nanjing University of Aeronautics and Astronautics · Tsinghua University
Abstract
Retrieval-Augmented Generation (RAG) has advanced repository-level code completion by retrieving external code snippets, API documentation, or type definitions to expand the model's contextual awareness. However, under the finite token budget of the context window, existing retrieval-augmented methods often saturate the budget with highly similar or even redundant code, which not only wastes tokens but also suppresses critical cross-file dependencies, preventing synergistic interaction between semantically similar reference snippets and cross-file dependency definitions. Therefore, further gains are limited by low knowledge density in the retrieved context rather than by model capacity. We propose SaraCoder, a retrieval-augmented framework that enhances knowledge density via hierarchical context pruning under a fixed context budget. A Hierarchical Feature Optimization module prunes an over-complete candidate pool in four stages. The freed tokens are then allocated to an External-Aware Identifier Disambiguator, which selectively injects only the most necessary cross-file dependency definitions. SaraCoder transforms context construction into a budget-aware optimization problem, balancing reference snippets and cross-file dependencies to build a context that is both knowledge-dense and semantically complete. Experiments on CrossCodeEval and RepoEval-Updated, across multiple backbone code LLMs, show that SaraCoder consistently outperforms strong RAG baselines such as GraphCoder and Repocoder in both code-level and identifier-level metrics, without increasing token usage, and yields synergistic gains when combined with other cross-file methods.
Figures & tables
| CrossCodeEval | RepoEval-Updated | |||
| Python | Java | Python | Java | |
| Total Repositories | 471 | 239 | 10 | 8 |
| Total Files | 14348 | 5868 | 3258 | 8260 |
| Total Task cases | 2665 | 2139 | 2000 | 1600 |
| Relationship | Definition and Type-Sensitive Characteristics | Syntax Examples (Python / Java) |
| Assignment | A variable acquires its type identity through assignment, which enables type inference and propagation. | Python: count: int = 10 ; Java: String s = new String() . |
| Contextual Binding | Temporary type bindings are created within specific syntactic structures, and their lifecycle is managed depending on the context. | Python: with open(file) as f: ; Java: try (BufferedReader br = ...) . |
| Reference | Existing variables or properties are accessed, which requires late-bound type resolution. | Python: obj.calculate() ; Java: this.value . |
| Type Declaration | Variable or return types are explicitly annotated, which provides the basis for static type checking. | Python: def func() -> list[str]: ; Java: List<Integer> list = new ArrayList<>() . |
| Parameter Constraint | Function parameters are constrained by types, which ensures input type validation. | Python: def sort(items: Sequence[T]) ; Java: void sort(List<? extends Comparable> l) . |
| Return Constraint | Function return values are constrained by types, which guarantees output type consistency. | Python: @return_type(float) ; Java: public int getValue() { ... } . |
| Dataset | Language | Methods | Models and Metrics | |||||||||||||||
| Codegen2-7b | Codegen25-7b | deepseek-coder-6.7b-instruct | CodeLlama-7b-Instruct | |||||||||||||||
| Code Match | Identifier Match | Code Match | Identifier Match | Code Match | Identifier Match | Code Match | Identifier Match | |||||||||||
| EM | ES | EM | F1 | EM | ES | EM | F1 | EM | ES | EM | F1 | EM | ES | EM | F1 | |||
| RepoEval-Updated | Python | No Rag | 17.40 | 32.54 | 23.75 | 30.21 | 19.55 | 34.48 | 25.75 | 32.16 | 11.50 | 30.33 | 15.30 | 22.39 | 17.35 | 33.05 | 23.55 | 30.53 |
| Shifted Rag | 32.70 | 59.22 | 40.10 | 55.66 | 36.45 | 61.96 | 43.20 | 58.31 | 20.90 | 42.95 | 26.50 | 38.88 | 33.90 | 60.28 | 41.50 | 56.39 | ||
| Vanilla Rag | 38.70 | 63.58 | 46.45 | 60.43 | 42.25 | 66.26 | 48.75 | 62.79 | 22.20 | 41.48 | 27.85 | 37.58 | 40.30 | 65.03 | 47.55 | 61.06 | ||
| Language | Methods | Codegen2-7b | Codegen25-7b | CodeLlama | |||||||||
| Code Match | Identifier Match | Code Match | Identifier Match | Code Match | Identifier Match | ||||||||
| EM | ES | EM | F1 | EM | ES | EM | F1 | EM | ES | EM | F1 | ||
| Python | No Rag | 5.44 | 57.85 | 11.71 | 42.22 | 7.77 | 60.52 | 14.45 | 45.40 | 9.49 | 61.97 | 16.44 | 47.36 |
| Shift Rag | 4.87 | 58.36 | 11.64 | 42.91 | 7.44 | 60.20 | 14.17 | 44.78 | 6.95 | 60.35 | 13.75 | 45.36 | |
| Vanilla Rag | 9.52 | 61.87 | 17.42 | 48.01 | 12.43 | 63.81 | 20.74 | 51.00 | 11.48 | 63.66 | 19.42 | 50.72 | |
| Saracoder | 12.16 | 54.16 | 18.37 | 45.47 | 11.50 | 44.90 | 16.22 | 38.95 | 13.32 | 48.04 | 19.54 | 42.34 | |
| Method | Codegen2-7b | deepseek-coder-6.7b-instruct | CodeLlama-7b-Instruct | |||
| #In | #Out | #In | #Out | #In | #Out | |
| No RAG | 1397.38 | 50.44 | 1383.12 | 95.22 | 1388.38 | 50.146 |
| Shifted RAG | 821.627 | 95.15 | 778.52 | 93.48 | 763.93 | 96.86 |
| HF_OP (top_k=10) | 1665.50 | 88.15 | 1621.92 | 90.86 | 1611.37 | 96.99 |
| HF_OP (top_k=4) | 1644.26 | 89.20 | 1596.83 | 88.57 | 1590.55 | 98.06 |
| Dataset | Language | Method | hit@1 | hit@5 | hit@10 |
| RepoEval_Updated | python | No Comp. | 25.40% | 32.15% | 34.35% |
| HF_OP | 25.00% | 34.50% | 36.45% | ||
| java | No Comp. | 12.69% | 19.81% | 22.25% | |
| HF_OP | 15.12% | 21.94% | 23.19% | ||
| CrossCodeEval | python | No Comp. | 0.11% | 0.26% | 0.38% |
| HF_OP | 2.61% | 3.97% | 4.16% |
LLM Code Generation
Large language model code generation studies how models translate instructions and context into executable programs and how to make them reliable.
See all 309 papers