File size: 11,632 Bytes
66b7ef5
03d6dd7
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
66b7ef5
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
47
48
49
50
51
52
53
54
55
56
57
58
59
60
61
62
63
64
65
66
67
68
69
70
71
72
73
74
75
76
77
78
79
80
81
82
83
84
85
86
87
88
89
90
91
92
93
94
95
96
97
98
99
100
101
102
103
104
105
106
107
108
109
110
111
112
113
114
115
116
117
118
119
120
121
122
123
124
125
126
127
128
129
130
131
132
133
134
135
136
137
138
139
140
141
142
143
144
145
146
147
148
149
150
151
152
153
154
155
156
157
158
159
160
161
162
163
164
165
166
167
168
169
170
171
172
173
174
175
176
177
178
179
180
<!doctype html>
<html lang="en">
<head>
<meta charset="utf-8">
<meta name="viewport" content="width=device-width, initial-scale=1">
<title>SpectRAG · Retrieve Context, Not Chunks</title>
<meta name="description" content="SpectRAG: weighted chunk graphs and spectral diffusion for token-budgeted context selection in multi-hop RAG.">
<meta property="og:title" content="SpectRAG · Retrieve context, not chunks">
<meta property="og:image" content="assets/00_cover.png">
<style>
  :root {
    --bg: #050B1A; --panel: #0A1630; --edge: #1C3466; --text: #E8F1FF; --muted: #93A5C8;
    --cyan: #4FD1FF; --green: #3DDC97; --yellow: #FFD166; --radius: 14px;
  }
  * { box-sizing: border-box; }
  html { scroll-behavior: smooth; }
  body { margin: 0; background: var(--bg); color: var(--text);
         font: 17px/1.65 -apple-system, BlinkMacSystemFont, "Segoe UI", Inter, Roboto, sans-serif; }
  main { max-width: 980px; margin: 0 auto; padding: 0 16px 80px; }
  a { color: var(--cyan); }
  img, video { display: block; width: 100%; height: auto; border-radius: var(--radius);
               border: 1px solid var(--edge); background: #000; }
  header { text-align: center; padding: 56px 0 28px; }
  .eyebrow { color: var(--cyan); letter-spacing: .14em; text-transform: uppercase; font-size: 13px; font-weight: 700; }
  h1 { font-size: clamp(34px, 6vw, 58px); line-height: 1.08; margin: 10px 0 14px; letter-spacing: -.02em; }
  h1 span { color: var(--cyan); }
  .lede { color: var(--muted); font-size: clamp(16px, 2.2vw, 20px); max-width: 720px; margin: 0 auto; }
  .authors { color: var(--muted); font-size: 14px; margin-top: 14px; }
  .btns { display: flex; gap: 10px; justify-content: center; flex-wrap: wrap; margin-top: 24px; }
  .btn { display: inline-flex; align-items: center; gap: 8px; padding: 10px 18px; border-radius: 999px;
         border: 1px solid var(--edge); background: var(--panel); color: var(--text); text-decoration: none;
         font-weight: 600; font-size: 15px; transition: border-color .15s, transform .15s; }
  .btn:hover { border-color: var(--cyan); transform: translateY(-1px); }
  .btn.primary { background: var(--cyan); color: var(--bg); border-color: var(--cyan); }
  section { margin-top: 64px; }
  h2 { font-size: clamp(24px, 3.4vw, 32px); margin: 0 0 6px; letter-spacing: -.01em; }
  .sub { color: var(--muted); margin: 0 0 20px; }
  figure { margin: 0; }
  figcaption { color: var(--muted); font-size: 14px; text-align: center; margin-top: 10px; }
  .quote { border-left: 3px solid var(--cyan); padding: 4px 0 4px 18px; font-size: 20px; margin: 28px 0 0; }
  .steps { display: grid; gap: 40px; }
  .step { display: grid; grid-template-columns: 1fr 1.35fr; gap: 24px; align-items: center; }
  .step:nth-child(even) .txt { order: 2; }
  .num { display: inline-grid; place-items: center; width: 30px; height: 30px; border-radius: 50%;
         background: var(--cyan); color: var(--bg); font-weight: 800; font-size: 15px; margin-bottom: 8px; }
  .step h3 { margin: 0 0 6px; font-size: 21px; }
  .step p { margin: 0; color: var(--muted); }
  .stats { display: grid; grid-template-columns: repeat(4, 1fr); gap: 12px; margin-bottom: 24px; }
  .stat { background: var(--panel); border: 1px solid var(--edge); border-radius: var(--radius); padding: 16px; }
  .stat b { display: block; font-size: 30px; line-height: 1.1; color: var(--cyan); }
  .stat span { color: var(--muted); font-size: 14px; }
  .charts { display: grid; grid-template-columns: 1fr 1fr; gap: 16px; }
  .note { background: var(--panel); border: 1px solid var(--edge); border-radius: var(--radius); padding: 18px 20px; }
  .note ul { margin: 6px 0 0; padding-left: 20px; color: var(--muted); }
  pre { background: var(--panel); border: 1px solid var(--edge); border-radius: var(--radius); padding: 16px;
        overflow-x: auto; font-size: 13px; line-height: 1.5; margin: 0; }
  .copy { margin-top: 10px; }
  footer { margin-top: 72px; text-align: center; color: var(--muted); font-size: 14px; }
  @media (max-width: 760px) {
    .step { grid-template-columns: 1fr; }
    .step:nth-child(even) .txt { order: 0; }
    .stats { grid-template-columns: 1fr 1fr; }
    .charts { grid-template-columns: 1fr; }
  }
</style>
</head>
<body>
<main>
  <header>
    <div class="eyebrow">Multi-hop RAG · arXiv 2610.36991</div>
    <h1>Stop retrieving chunks.<br><span>Start retrieving context.</span></h1>
    <p class="lede">SpectRAG builds a weighted chunk graph from six evidence signals and uses its Laplacian spectrum to select a context set that is <b>relevant, diverse and connected</b>, all under a fixed token budget.</p>
    <p class="authors">Zafer Sahinoglu · Abdulazeez Mohammed · Buse Yaren Kazangirler · Cahit Berkay Kazangirler</p>
    <div class="btns">
      <a class="btn primary" href="https://arxiv.org/abs/2610.36991" target="_blank" rel="noopener">📄 Paper</a>
      <a class="btn" href="https://github.com/SightAndCite/SpectRAG" target="_blank" rel="noopener">💻 Code</a>
      <a class="btn" href="https://huggingface.co/papers/2610.36991" target="_blank" rel="noopener">🤗 Paper page</a>
      <a class="btn" href="#video">🎬 Watch the explainer</a>
    </div>
  </header>

  <figure>
    <img src="assets/01_hero_topk_vs_spectrag.gif" alt="Animation: classic top-k retrieval picks six near-duplicate chunks and finds 1 of 3 gold passages; SpectRAG seeds, expands, diffuses and selects a diverse set that finds 3 of 3.">
    <figcaption>Same question, same 6-chunk budget. Top-k finds 1/3 of the gold evidence; SpectRAG finds 3/3. (Illustrative toy corpus.)</figcaption>
  </figure>

  <p class="quote">Top-k ranks chunks one at a time. Multi-hop questions need a <b>set</b> of chunks that works together as evidence.</p>

  <section id="how">
    <h2>How it works</h2>
    <p class="sub">An offline pass builds the graph once; a five-stage online pass selects context for each query.</p>
    <div class="steps">
      <div class="step">
        <div class="txt"><div class="num">1</div><h3>A chunk graph built from six signals</h3>
          <p>Semantic similarity, document adjacency, section hierarchy, shared entities, LLM-generated utility questions and citations are fused into one weighted edge.</p></div>
        <img src="assets/02_six_signals_graph_build.gif" alt="Animation: chunks from five documents are connected signal by signal into a weighted chunk graph." loading="lazy">
      </div>
      <div class="step">
        <div class="txt"><div class="num">2</div><h3>Two geometries for every chunk</h3>
          <p>The dense embedding captures what a chunk says. The 32-d spectral coordinate from the normalized Laplacian captures where it lives in the corpus.</p></div>
        <img src="assets/03_spectral_coordinates.gif" alt="Animation: points morph from an overlapping embedding layout into well-separated spectral communities." loading="lazy">
      </div>
      <div class="step">
        <div class="txt"><div class="num">3</div><h3>Relevance diffuses along the graph</h3>
          <p>Hybrid seeds (dense + BM25 + utility questions) are expanded two hops and re-scored with spectral closeness and Personalized PageRank, so bridge evidence surfaces.</p></div>
        <img src="assets/04_spectral_diffusion.gif" alt="Animation: relevance heat spreads from three seed nodes across a graph." loading="lazy">
      </div>
      <div class="step">
        <div class="txt"><div class="num">4</div><h3>Token-budgeted selection</h3>
          <p>A protected core, a coverage-aware tail with a precision floor, and a backfill fill a ~12k-token window, adapting to 10–15 chunks per query.</p></div>
        <img src="assets/05_token_budget_selection.gif" alt="Animation: candidate chunks fill a 12,000-token context window; redundant and low-precision chunks are skipped." loading="lazy">
      </div>
    </div>
    <figure style="margin-top:40px">
      <img src="assets/online-offline-main-pipeline.png" alt="Full SpectRAG pipeline diagram: offline indexing and online query-time retrieval." loading="lazy">
      <figcaption>The full pipeline: offline corpus indexing and online query-time retrieval.</figcaption>
    </figure>
  </section>

  <section id="video">
    <h2>Explainer video</h2>
    <p class="sub">A 98-second narrated walkthrough. Captions are available in the player.</p>
    <video controls preload="metadata" poster="assets/00_cover.png">
      <source src="assets/SpectRAG_explainer_voiceover.mp4" type="video/mp4">
      <track kind="captions" src="assets/SpectRAG_explainer_voiceover.vtt" srclang="en" label="English" default>
    </video>
  </section>

  <section id="results">
    <h2>Results</h2>
    <p class="sub">MultiHopRAG (2,556 gold-answer questions) and four UltraDomain corpora, against NaiveRAG, Hybrid, HyDE and LightRAG. Every system uses the same generator.</p>
    <div class="stats">
      <div class="stat"><b>91.8%</b><span>overall gold-evidence recall (next best 76.1%)</span></div>
      <div class="stat"><b>95.1%</b><span>exact match on inference questions</span></div>
      <div class="stat"><b>~6×</b><span>smaller index than LightRAG (46 vs 274 MB)</span></div>
      <div class="stat"><b>&gt;50%</b><span>diversity win rate vs every baseline</span></div>
    </div>
    <div class="charts">
      <img src="assets/chart_02_recall_by_depth.png" alt="Line chart: recall at 2, 5, 10 and overall for five systems; SpectRAG reaches 91.8% overall." loading="lazy">
      <img src="assets/chart_01_index_footprint.png" alt="Bar charts: index size 46 MB vs 274 MB and node counts per corpus, SpectRAG vs LightRAG." loading="lazy">
      <img src="assets/chart_03_accuracy_by_question_type.png" alt="Dot plot: exact match by question type; SpectRAG leads on inference at 95.1%." loading="lazy">
      <img src="assets/chart_04_diversity_win_rate.png" alt="Bar chart: SpectRAG diversity win rate above 50% against all four baselines in both configurations." loading="lazy">
    </div>
    <div class="note" style="margin-top:20px">
      <b>Honest trade-offs</b>
      <ul>
        <li>Hybrid retrieval leads at the very top of the ranking (Recall@2, Recall@5, MRR); SpectRAG wins on breadth.</li>
        <li>End-to-end accuracy gains are narrow (EM 71.2 vs 70.6 for the next best): better retrieval saturates with short multi-hop answers.</li>
        <li>On unanswerable (null) questions SpectRAG is behind the vector baselines, and signal weights can need per-corpus tuning.</li>
      </ul>
    </div>
  </section>

  <section id="cite">
    <h2>Citation</h2>
<pre id="bib">@misc{sahinoglu2026spectragweightedchunkgraphs,
      title={SpectRAG: Weighted Chunk Graphs for Token-Budgeted Context Selection in Multi-Hop Retrieval-Augmented Generation},
      author={Zafer Sahinoglu and Abdulazeez Mohammed and Buse Yaren Kazangirler and Cahit Berkay Kazangirler},
      year={2026},
      eprint={2610.36991},
      archivePrefix={arXiv},
      primaryClass={cs.AI},
      url={https://arxiv.org/abs/2610.36991},
}</pre>
    <button class="btn copy" type="button" id="copyBib">Copy BibTeX</button>
  </section>

  <footer>SpectRAG is open source under the MIT license · <a href="https://github.com/SightAndCite/SpectRAG">GitHub</a></footer>
</main>
<script>
  document.getElementById('copyBib').addEventListener('click', async (e) => {
    try { await navigator.clipboard.writeText(document.getElementById('bib').textContent);
          e.target.textContent = 'Copied ✓'; }
    catch { e.target.textContent = 'Select the text above to copy'; }
    setTimeout(() => { e.target.textContent = 'Copy BibTeX'; }, 2000);
  });
</script>
</body>
</html>