| <!doctype html> |
| <html lang="en"> |
| <head> |
| <meta charset="utf-8"> |
| <meta name="viewport" content="width=device-width, initial-scale=1"> |
| <title>ThinkRetrieve Research Explorer — reasoning-aware retrieval</title> |
| <link rel="canonical" href="https://tronrover-thinkretrieve-research-explorer.static.hf.space/"> |
| <meta name="description" content="Inspect recorded retrieval decisions from ThinkRetrieve, accepted to Findings of EMNLP 2026. Compare four methods across all six exploratory cases."> |
| <meta name="robots" content="index, follow, max-image-preview:large"> |
| <style> |
| :root { font: 16px/1.6 system-ui, sans-serif; color: #15243a; background: #f4f7fb; } |
| body { max-width: 1160px; margin: auto; padding: 32px 24px 64px; } |
| h1 { font-size: clamp(2rem, 5vw, 3.5rem); line-height: 1.12; letter-spacing: -.04em; margin: 16px 0; } |
| h2 { font-size: 1.25rem; margin-top: 0; } |
| a { color: #175ead; text-underline-offset: .2em; } |
| .tag { color: #175ead; font-weight: 700; } |
| .intro { max-width: 840px; } |
| nav, .controls { display: flex; gap: 16px 24px; flex-wrap: wrap; margin: 24px 0; } |
| select { font: inherit; padding: 8px; border: 1px solid #a4b3c7; border-radius: 6px; background: white; color: #15243a; } |
| label { display: grid; gap: 6px; } |
| .notice { padding: 18px; background: #e8eef8; border-left: 4px solid #4076b8; border-radius: 4px; } |
| .grid { display: grid; grid-template-columns: repeat(2, minmax(0, 1fr)); gap: 18px; } |
| article { padding: 24px; border: 1px solid #d7dfeb; border-radius: 14px; background: white; } |
| article p { white-space: pre-wrap; overflow-wrap: anywhere; } |
| .right { color: #146437; font-weight: 700; } .wrong { color: #963b2f; font-weight: 700; } |
| table { width: 100%; border-collapse: collapse; margin: 24px 0; } |
| th, td { text-align: left; padding: 12px 8px; border-bottom: 1px solid #cbd6e6; } |
| .table-wrap { overflow-x: auto; } |
| footer { margin-top: 40px; border-top: 1px solid #cbd6e6; padding-top: 24px; } |
| :focus-visible { outline: 3px solid #175ead; outline-offset: 3px; } |
| @media (max-width: 720px) { .grid { grid-template-columns: 1fr; } body { padding: 20px 16px; } } |
| </style> |
| </head> |
| <body> |
| <header class="intro"> |
| <span class="tag">Accepted to Findings of EMNLP 2026</span> |
| <h1>What changes when retrieval waits for reasoning?</h1> |
| <p>ThinkRetrieve uses an intermediate answer to retrieve a worked solution and inject it into the ongoing reasoning trace. Inspect the recorded decisions below, including where the method fails.</p> |
| <nav aria-label="Research resources"><a href="https://arxiv.org/abs/2608.10928">Read the paper</a><a href="https://github.com/itsvaibhav01/ThinkRetrieve">Code and tutorial</a><a href="https://itsvaibhav01.github.io/ThinkRetrieve/paper/#citation">Cite the work</a></nav> |
| </header> |
| <main> |
| <p class="notice"><strong>Recorded demonstration, not live inference.</strong> Six synthetic incidents and private tool routes, selected after exploratory screening. These are not held-out results, a general agent accuracy estimate, or a biological safety benchmark. This experiment is separate from the paper's benchmarks.</p> |
| <div class="controls"> |
| <label>Recorded model<select id="model"><option value="qwen35_9b">Qwen 3.5 9B</option><option value="qwen35_4b">Qwen 3.5 4B</option></select></label> |
| <label>Inspect case<select id="case"></select></label> |
| </div> |
| <p id="status" role="status">Loading recorded outputs…</p> |
| <div class="table-wrap"><table><caption>All six recorded cases for the selected model</caption><thead><tr><th scope="col">Method</th><th scope="col">Correct routes</th><th scope="col">Accuracy</th></tr></thead><tbody id="summary"></tbody></table></div> |
| <section class="grid" id="cases" aria-label="Method comparison"></section> |
| <section class="intro" style="margin-top:32px"> |
| <h2>A useful next experiment</h2> |
| <p>Hold the model, memory bank, and evaluation set fixed. Compare retrieving from the original question with retrieving from an intermediate answer. Then vary whether examples are prepended or injected into the trace. Measure total model calls, generated and injected tokens, retrieval overhead, and failures.</p> |
| <p><a href="https://github.com/itsvaibhav01/ThinkRetrieve/blob/main/thinkretrieve/examples/compare_tts_vs_thinkretrieve.py">Use the existing four-method comparison runner</a>. Use fresh output directories per configuration; cached runs are resumed by example index. The runner is a starting point, and further controls are needed to isolate query quality from additional model calls.</p> |
| </section> |
| </main> |
| <footer class="intro"> |
| <p>Source: <a href="https://github.com/itsvaibhav01/ThinkRetrieve/tree/7e245c10b05a5b1c83f283a659cd210a0e19c8fb/thinkretrieve/benchmarks/science_agent">recorded JSON, runner, and experiment design at revision 7e245c1</a>.</p> |
| <p>Vaibhav Singh, Soumya Suvra Ghosal, Sarvesh Gharat, Soumyabrata Pal, Ramasuri Narayanam, and Dinesh Manocha. <em>ThinkRetrieve: Retrieval-Augmented Reasoning Traces for Test-Time Scaling.</em> 2026. <a href="https://doi.org/10.48550/arXiv.2608.10928">DOI: 10.48550/arXiv.2608.10928</a>.</p> |
| </footer> |
| <script> |
| 'use strict'; |
| const labels = {plain: 'Plain reasoning', rag: 'Prompt-level RAG', tts: 'Extra thinking (TTS)', thinkretrieve: 'ThinkRetrieve'}; |
| const models = document.getElementById('model'); |
| const choices = document.getElementById('case'); |
| const status = document.getElementById('status'); |
| const cache = {}; |
| function node(tag, text) { const el = document.createElement(tag); el.textContent = text; return el; } |
| function render() { |
| const rows = cache[models.value]; |
| if (!rows) return; |
| const summary = document.getElementById('summary'); |
| const cards = document.getElementById('cases'); |
| summary.replaceChildren(); cards.replaceChildren(); |
| for (const [arm, title] of Object.entries(labels)) { |
| const all = rows.filter(r => r.arm === arm); |
| const correct = all.filter(r => r.correct).length; |
| const tr = document.createElement('tr'); |
| tr.append(node('th', title), node('td', `${correct}/${all.length}`), node('td', `${(100 * correct / all.length).toFixed(1)}%`)); |
| tr.firstChild.scope = 'row'; summary.append(tr); |
| const row = all.find(r => r.index === Number(choices.value)); |
| const card = document.createElement('article'); |
| card.append(node('h2', title)); |
| const result = node('p', `${row.correct ? 'Correct' : 'Incorrect'} · selected ${row.prediction ?? 'no route'} · expected ${row.gold}`); |
| result.className = row.correct ? 'right' : 'wrong'; card.append(result); |
| const fields = arm === 'thinkretrieve' |
| ? [['interim_answer', 'Intermediate answer'], ['dynamic_retrieval', 'Retrieved using intermediate answer']] |
| : arm === 'rag' ? [['raw_retrieval', 'Retrieved from original question']] : []; |
| for (const [key, label] of fields) { card.append(node('strong', label), node('p', row[key] ?? 'Not recorded')); } |
| card.append(node('strong', 'Final answer'), node('p', row.answer)); cards.append(card); |
| } |
| status.textContent = 'All six cases are available. Case 1 includes a ThinkRetrieve failure in the 9B run.'; |
| } |
| async function load() { |
| const model = models.value; |
| status.textContent = 'Loading recorded outputs…'; |
| try { |
| if (!cache[model]) { |
| const response = await fetch(`${model}.json`); |
| if (!response.ok) throw new Error(`HTTP ${response.status}`); |
| const rows = await response.json(); |
| if (!Array.isArray(rows) || rows.length !== 24) throw new Error('Unexpected data format'); |
| for (const arm of Object.keys(labels)) { |
| const subset = rows.filter(r => r.arm === arm); |
| if (subset.length !== 6 || new Set(subset.map(r => r.index)).size !== 6) throw new Error('Incomplete case set'); |
| } |
| cache[model] = rows; |
| } |
| if (model !== models.value) return; |
| render(); |
| } catch (error) { |
| document.getElementById('summary').replaceChildren(); |
| document.getElementById('cases').replaceChildren(); |
| status.textContent = `Could not load the recorded data (${error.message}). The original JSON is linked below.`; |
| } |
| } |
| for (let i = 0; i < 6; i++) { const option = node('option', `Case ${i + 1}`); option.value = String(i); choices.append(option); } |
| models.addEventListener('change', load); choices.addEventListener('change', render); load(); |
| </script> |
| </body> |
| </html> |
|
|