Paper · PDF · Project page · Code
ThinkRetrieve makes a reasoning model recall worked examples mid-thought. Instead of only "thinking longer" (which drifts and compounds errors), it pauses at each reasoning step, retrieves the most similar solved example from a bank, and injects it into the thinking trace — guidance on how to reason, not just what facts to use.
It works over any chat API (OpenAI-compatible, Anthropic, Amazon Bedrock, or a local model via Ollama / LM Studio / MLX / llama.cpp) — no GPU or vLLM required.
pip install "thinkretrieve[faiss]"
Quickstart
from thinkretrieve import ThinkRetrieve, FaissRetriever, OpenAICompatBackend
# 1. A bank of solved (question, worked-solution) pairs — a dataset, your docs, past tickets…
bank = FaissRetriever.from_examples([
("A jacket costs $120 and is discounted 25%. Final price?",
"Discount = 0.25*120 = 30. Final = 120-30 = 90. Answer: $90"),
("What is 15% of 80?", "0.15*80 = 12. Answer: 12"),
])
# 2. Any chat model — local (shown) or hosted.
backend = OpenAICompatBackend(model="qwen3:4b", base_url="http://localhost:11434/v1")
# 3. Reason with mid-thought retrieval.
result = ThinkRetrieve(backend, bank).run(
"A phone costs $250 after a 20% discount. What was the original price?")
print(result.answer) # the final answer
print(result.think_trace) # full reasoning, with injected examples visible
print(result.retrievals) # what was retrieved, when, and why
How it works
At each reasoning boundary the model elicits an interim answer, retrieves the most
similar solved example (E5 + FAISS by default), injects it into the trace, and
continues — repeating until the thinking budget is spent. Passing
retriever=None gives you the plain "think longer" baseline for A/B comparison.
Results
Across 5 reasoning models × 4 benchmarks (paper), ThinkRetrieve beats standard thinking, sequential test-time scaling (TTS), static in-context ICL, and random per-step retrieval on every cell — and, because injected tokens count against the budget but aren't generated, it produces fewer model tokens than TTS at the same budget (~6% wall-clock overhead).
Sequential TTS degrades or plateaus as the budget grows; ThinkRetrieve keeps improving — most dramatically on the hardest benchmark:
| Best accuracy (%) | GSM-8K | MATH-500 | AIME 2025 |
|---|---|---|---|
| TTS / Ours | TTS / Ours | TTS / Ours | |
| Qwen3-1.7B | 90.3 / 92.1 | 91.0 / 92.5 | 22.2 / 35.6 |
| Qwen3-4B | 95.1 / 96.8 | 93.7 / 96.1 | 64.4 / 66.7 |
| Qwen3-8B | 96.4 / 97.2 | 94.0 / 94.8 | 68.9 / 71.1 |
Use cases
1 · Reason over a dataset (math, science QA, …)
Index any dataset with worked solutions and go. See
examples/sciq_example.py for a full SciQ run
(build bank from the train split → answer test questions → score):
python examples/sciq_example.py --limit 30
Ready-made banks: NuminaMath, MetaMathQA, GSM8K, MATH, SciQ — anything with
(question, step-by-step solution) pairs.
2 · Procedural memory for agents
Most agent memory stores facts. A ThinkRetrieve bank stores procedures —
solved tasks — and recalls them mid-reasoning. The bank grows as the agent
works (examples/agent_memory.py):
result = agent.run(task)
if verified(result): # tests pass / human approves
memory.add(task, result.answer) # the agent now remembers HOW
memory.save("agent_memory")
3 · Upgrade an existing RAG stack
Prompt-level RAG is ~neutral on reasoning tasks; injecting the same content
inside the trace is what wins (paper §5). Keep your index — wrap it in a 5-line
retriever (examples/rag_integration.py):
from thinkretrieve.types import Example
class MyStore: # pgvector / Pinecone / Chroma / …
def retrieve(self, question, interim_answer="", k=1, exclude_ids=frozenset()):
hits = my_index.search(f"{question}\n{interim_answer}", k + len(exclude_ids))
return [Example(id=h.id, question=h.q, solution=h.body)
for h in hits if h.id not in exclude_ids][:k]
ThinkRetrieve(backend, MyStore()).run(question)
Compare it yourself (one command)
python examples/compare_tts_vs_thinkretrieve.py --backend openai --model qwen3:4b
Runs plain / RAG / long-thinking / ThinkRetrieve at the same budget and prints
the table. Add --backend bedrock --model qwen.qwen3-32b-v1:0 for Amazon Bedrock.
Backends
| Backend | Import | Use for |
|---|---|---|
| OpenAI-compatible | OpenAICompatBackend |
Ollama, LM Studio, MLX, llama.cpp, vLLM, OpenAI, Together, Groq, DeepSeek, OpenRouter |
| Anthropic | AnthropicBackend |
Claude models (pip install "thinkretrieve[anthropic]") |
| Amazon Bedrock | BedrockConverseBackend |
Bedrock models (pip install "thinkretrieve[bedrock]") |
Or subclass ChatTranscriptBackend and implement one _chat() method.
Install options
pip install "thinkretrieve[faiss]" # core + FAISS retrieval (recommended)
pip install "thinkretrieve[faiss,anthropic]" # + Anthropic
pip install "thinkretrieve[all]" # everything
No GPU needed: retrieval runs on CPU / Apple Silicon; generation runs wherever your model lives. Full walkthrough in TUTORIAL.md.
Citation
@article{thinkretrieve2026,
title = {ThinkRetrieve: Retrieval-Augmented Reasoning Traces for Test-Time Scaling},
author = {Singh, Vaibhav and Ghosal, Soumya Sourav and Gharat, Sarvesh and
Pal, Soumyabrata and Narayanam, Ramasuri and Manocha, Dinesh},
journal = {arXiv preprint arXiv:2608.10928},
year = {2026},
url = {https://arxiv.org/abs/2608.10928}
}
License
MIT
Metadata
Release files for thinkretrieve 0.1.2
For a detailed explanation of source distributions (sdists) and built distributions (wheels), please see the package formats documentation.
Source distribution (sdist)
| File | Size | Uploaded | Provenance | Actions |
|---|---|---|---|---|
| thinkretrieve-0.1.2.tar.gz | 719.9 kB | Without provenance | Details for thinkretrieve-0.1.2.tar.gz |
Built distribution (wheel)
| File | Interpreter | ABI | Platform | Actions Reset |
|---|---|---|---|---|
| thinkretrieve-0.1.2-py3-none-any.whl | Python 3 | none | any | Details for thinkretrieve-0.1.2-py3-none-any.whl |
Total release size: 741.6 kB
Release files / thinkretrieve-0.1.2.tar.gz
| Download URL | thinkretrieve-0.1.2.tar.gz |
|---|---|
| Size | 719.9 kB |
| Tags | Source |
|
SHA-256 checksum How to use checksums |
afcaabb27d84d334a9d8db5637e9ec04dd0687a92313222657b24fc720101d6e
|
|
BLAKE2b-256 checksum How to use checksums |
f4df1680f13c58a894fbc2cbfbce285090e3ddedb66cf7106ee15f6147667e7b
|
| Upload date | |
|
Uploaded using Trusted Publishing? What is trusted publishing? |
No |
| Uploaded via |
twine/7.0.0 CPython/3.12.8
|
Release files / thinkretrieve-0.1.2-py3-none-any.whl
| Download URL | thinkretrieve-0.1.2-py3-none-any.whl |
|---|---|
| Size | 21.7 kB |
| Tags | Python 3 |
|
SHA-256 checksum How to use checksums |
f1f456f36129ab8997c9b050287781a51385c087a6bcc29fc9370d48a8a2124e
|
|
BLAKE2b-256 checksum How to use checksums |
a914fbb71c85db30644c03deecf4f8b74e75a66167aca86a3eeb99ed2e37f216
|
| Upload date | |
|
Uploaded using Trusted Publishing? What is trusted publishing? |
No |
| Uploaded via |
twine/7.0.0 CPython/3.12.8
|
Security for thinkretrieve 0.1.2
Provenance
Provenance describes where a file came from. On PyPI, provenance is shared via attestations, which provide a verifiable record of the build or publishing details. View details, limitations and caveats.
No provenance found
None of the files in this release were uploaded with provenance metadata.
A note on package security
PyPI is a repository for distributing packages, not a service for auditing them. While third-party security researchers and our staff do their best to detect and remove malicious packages, PyPI cannot guarantee the quality, security or suitability of any given package.
To learn more about protecting yourself from malicious actors, visit our package security documentation.