Skip to content
qpiaiPublic

About

Reasoning tree with validation

Resources

Contributing

Security policy

Stars

19 stars

Watchers

0 watching

Forks

Latest commit

Β 

History

19 Commits

Folders and files

Repository files navigation

🌳 ReTreVal: Reasoning Tree with Validation and Cross-Problem Memory for Large Language Models

Watch an LLM grow a validated reasoning tree, refine each node with tools, and remember what works β€” live.

arXiv License: Apache 2.0 LangGraph Next.js UI Python 3.9+

Demo Β· Mission Β· Why Β· How it works Β· Web UI Β· Quickstart Β· Results


🎬 Demo

demo.mp4
β–ΆοΈŽ Click to play (with sound) β€” two prompts, two domains. Β Β·Β  Silent GIF: docs/demo.gif Β Β·Β  Full MP4: docs/demo.mp4 Β Β·Β  screenshot

Two prompts, two domains β€” number theory (divisors of 196) and deep learning (the GELU formula) β€” each solved live: the agent plans a tree, expands candidate approaches, refines each with tools (python_exec, calculator, arxiv_search, wikipedia…), scores them, backtracks out of dead ends, and remembers what worked. Every step streams to the UI in real time.


🎯 Mission

Build an agent that learns. Most reasoning frameworks run each problem cold; ReTreVal accumulates what worked and what failed across runs and feeds it into every new attempt β€” one pipeline, any task, continuously improving, no fine-tuning.


πŸ€” Why ReTreVal

ReTreVal treats reasoning as search with feedback β€” explore candidate paths as a tree, validate and prune them, then remember the outcome for next time. Concretely, that means:

  • 🌳 Tree + validation, not just a chain β€” candidates are explored as a branching tree, each scored by self-eval and an external LLM critic; the best path advances.
  • πŸ› οΈ Tools at every node β€” a ReAct loop lets the model call a calculator, equation solver, python_exec, and web/Wikipedia/arXiv search to verify its reasoning instead of guessing.
  • 🧠 Memory that compounds β€” successful patterns and failure modes persist to disk and are injected into future problems; performance improves with scale, not just with a better model.
  • πŸ” Backtracking β€” on a failed validation the agent navigates to an unexplored sibling with structured failure context, instead of giving up.
  • 🧩 Task-agnostic β€” the same graph works across math, science, multiple-choice, and open-ended tasks; plug in a new evaluator, not a new agent.
  • ⚑ Four backends, one interface β€” Gemini, OpenAI, Ollama, and vLLM behind a provider-agnostic facade; swap with an env var.
  • πŸ” Auditable β€” every node, score, tool call, and memory write is inspectable; the web UI renders the whole tree and trace.

🧠 How it works

ReTreVal is a compiled LangGraph state graph. For each problem it grows an adaptive reasoning tree whose depth/branching scale with estimated complexity. Each node self-improves through a tool-augmented ReAct loop, is scored by dual validation (0.6 Γ— local self-eval + 0.4 Γ— external critic), and on validation failure performs typed-failure backtracking. Hard problems are decomposed into sub-tasks. A persistent memory feeds past successes and failures into every new attempt.

ReTreVal architecture: Problem β†’ Complexity Estimator β†’ Plan β†’ Expand tree β†’ per-node tool-grounded refinement loop (tool registry + execution) β†’ Critique β†’ Dual scoring β†’ Backtracking / Failure analysis, with Task Decomposition, Prune, Synthesize, Validate, Feedback, and a Gradient-refined Memory, orchestrated as a LangGraph pipeline.
Step What happens
Plan Estimate complexity (1–5) and size the tree (depth/branching) adaptively; inject relevant memory.
Expand Generate K candidate reasoning branches from the current node.
Tool-augmented refine Each node runs a ReAct loop where the LLM calls tools (calculator, equation solver, python_exec, web/Wikipedia/arXiv) to verify and improve its reasoning.
Critique + dual score Pairwise cross-critique plus local self-eval, combined as 0.6 Γ— local + 0.4 Γ— cross; the best branch advances.
Memory update Insights and failure patterns are written back (de-duplicated, confidence-weighted) for future problems.
Decompose Hard problems (complexity β‰₯ 4, low score) are split into dependency-ordered sub-tasks, solved, and aggregated.
Synthesize β†’ Validate Produce the final answer and validate it. By default the agent solves without seeing the reference answer; pass --oracle to let it use the reference (research only).
Backtrack On validation failure, navigate to an unexplored sibling branch with structured failure context injected.

How the memory works

The memory (src/utils/memory.py, class Memory) is a persistent buffer of structured entries β€” insights/successes (patterns that produced correct answers) and failures (what went wrong and why). Each entry carries a confidence score, and new entries are de-duplicated against existing ones by keyword (Jaccard) overlap rather than stored blindly. After every problem the outcome is written back, confidence is nudged up on success / down on failure, and the buffer is serialized to a human-readable memory.md (with an embedded JSON block for exact reload).

On the next problem the most relevant entries β€” ranked by keyword overlap Γ— confidence β€” are injected into the prompts. The buffer persists across runs via that shared file, so a fresh batch picks up everything the previous batch learned. Memory is on by default; point it at a file with --memory-file <path> (or MEMORY_FILE), or disable it with --no-memory.


πŸ–₯️ Web UI

A chat where you can watch the agent think. Type a problem on the left; on the right the reasoning tree grows node-by-node and the trace streams live β€” then the validated answer (with rendered math/code) lands back in the chat.

%%{init: {'theme':'base', 'themeVariables': {'fontFamily':'Inter, sans-serif','lineColor':'#8b5cf6'}}}%%
flowchart LR
    You([πŸ§‘ You]) -->|"type a problem"| UI
    UI["πŸ–₯️ Web UI Β· Next.js<br/>πŸ’¬ chat Β· 🌳 tree Β· πŸ“œ logs"] -->|"GET /api/solve"| API
    API["βš™οΈ FastAPI bridge"] --> Agent["πŸ€– LangGraphAgent<br/>plan β†’ expand β†’ refine β†’ score β†’ validate"]
    Agent -. "live events stream back (SSE)" .-> UI

    classDef pink fill:#fce7f3,stroke:#ec4899,color:#831843;
    classDef violet fill:#ede9fe,stroke:#8b5cf6,color:#4c1d95;
    class UI pink
    class API,Agent violet
Loading

Run it

# 1 β€” backend bridge.  Mock mode = no API key, streams a deterministic demo run.
cd retreval_oss && . .venv/bin/activate
pip install -r server/requirements.txt
RETREVAL_MOCK=1 uvicorn server.app:app --port 7373

# 2 β€” UI (in a second shell)
cd web && npm install && npm run dev          # β†’ http://localhost:7575

Open http://localhost:7575. To drive the real agent instead of the mock, configure a provider in .env (e.g. LLM_PROVIDER=gemini, GEMINI_API_KEY=…) and start the backend without RETREVAL_MOCK. The UI auto-detects which provider the backend is using.

Using it

  • Ask anything β€” type a problem and press Enter, or click a suggested example. It's domain-general: math, science, coding, knowledge, or open-ended all work.
  • Watch the tree (right, top) β€” every node is a candidate approach, colored by score; the β˜… pink node is the current best and the highlighted edge is the active path. Drag to pan, scroll to zoom.
  • Follow the trace (right, bottom) β€” plan β†’ expand β†’ tool-refine β†’ score β†’ backtrack β†’ synthesize β†’ validate, with each tool call (calculator, python_exec, arxiv_search, wikipedia…) and memory write streaming in.
  • Tune the run (top bar) β€” choose the provider, set iterations (how many tree passes), toggle memory, and switch πŸŒ™ / β˜€οΈ themes.
  • Resize / focus β€” drag the divider to resize the panes, double-click it to reset to 50/50, or hit βœ• to collapse the panel for a distraction-free chat.

Ports are chosen to be memorable and browser-safe: UI 7575, API 7373.

Build a static bundle for deployment with npm run build (outputs web/out/, serve with any static host). More detail in web/README.md.


πŸš€ Quickstart

# 1 β€” clone and install
git clone https://github.com/qpiai/retreval.git && cd retreval
python -m venv .venv && source .venv/bin/activate
pip install -r requirements.txt

# 2 β€” configure a provider
cp .env.example .env
# set LLM_PROVIDER and your API key in .env
# 3 β€” solve a single problem
python -m src.agents.agent_main \
  --provider gemini \
  --prompt "How many positive whole-number divisors does 196 have?" \
  --iterations 2 --verbose

# 4 β€” evaluate on MATH-500 (memory persists across runs)
python -m src.agents.math500_eval --provider gemini --limit 100 --iterations 1

# 5 β€” summarize a run
python analyze_results.py            # newest run in results/math500/

Results land in results/math500/math500_eval_YYYYMMDD_HHMMSS.jsonl. Run the evaluator again on the next batch β€” the memory from the first carries over automatically.


πŸ“Š Results

From the paper (arXiv 2601.02880).

🎯 85.8% accuracy on MATH-500 (429/500), +7.2 pp over Self-Refine β€” and 54.4% on MMLU-Pro. Ablations confirm each component pulls its weight: removing memory drops accuracy to 76.8%, removing backtracking to 78.4%.

MATH-500 β€” Overall Accuracy

Method Accuracy
Zero-Shot CoT 77.2%
ReAct 73.2%
ToT 77.4%
LATS 77.6%
Self-Refine 78.6%
ReTreVal 85.8%

Reproducibility note. The bundled math500_eval.py reports exact-match accuracy (the 85.8% metric β€” fast, deterministic, no extra API cost).


πŸ”Œ Supported tasks

The OSS release ships a MATH-500 evaluator as the reference implementation; the agent itself is task-agnostic. The framework has been evaluated on MATH-500, GSM8K, GPQA, and creative writing. Adding a task needs two things: a loader (yields (question, expected_answer)) and an answer normalizer β€” everything else stays the same.


🧩 Repository layout

.
β”œβ”€β”€ src/
β”‚   β”œβ”€β”€ agents/        # LangGraph tree agent, per-node ReAct executor, CLI, MATH-500 eval
β”‚   β”œβ”€β”€ tools/         # planner, refiner+critique, dual scoring, feedback/backtrack,
β”‚   β”‚                  #   decomposition, synthesis, computation, search
β”‚   β”œβ”€β”€ clients/       # provider router + Gemini / OpenAI / Ollama / vLLM backends
β”‚   └── utils/         # persistent Memory + vLLM KV-cache prompt structuring
β”œβ”€β”€ web/               # Next.js chat UI (chat Β· reasoning tree Β· live logs)
β”œβ”€β”€ server/            # FastAPI bridge β€” streams the agent to the UI over SSE
β”œβ”€β”€ scripts/           # headless-browser smoke test for the UI
β”œβ”€β”€ docs/              # demo.mp4 / demo.gif / screenshot.png
β”œβ”€β”€ data/math/         # bundled MATH-500 dataset
β”œβ”€β”€ results/math500/   # evaluation outputs (JSONL, timestamped)
β”œβ”€β”€ analyze_results.py # summarize a MATH-500 run (accuracy, by level/subject)
β”œβ”€β”€ run_math500_vllm.py
β”œβ”€β”€ .env.example
└── requirements.txt

βš™οΈ Configuration

LLM provider β€” no code changes to switch backends
# Cloud
LLM_PROVIDER=gemini
GEMINI_API_KEY=...
GEMINI_MODEL=gemini-2.5-flash        # or gemini-2.5-pro

LLM_PROVIDER=openai
OPENAI_API_KEY=...
OPENAI_MODEL=gpt-4o-mini             # or gpt-4o

# Local
LLM_PROVIDER=ollama
OLLAMA_BASE_URL=http://localhost:11434
OLLAMA_MODEL=qwen2.5:7b

LLM_PROVIDER=vllm
VLLM_BASE_URL=http://localhost:8000/v1
VLLM_MODEL=Qwen/Qwen2.5-7B-Instruct
Provider Best for Suggested models
Gemini Free tier, strong reasoning gemini-2.5-flash, gemini-2.5-pro
OpenAI GPT-4o quality bar gpt-4o-mini, gpt-4o
Ollama On-premise, privacy qwen2.5:7b, llama3.1:8b
vLLM High-throughput local batch eval Qwen/Qwen2.5-7B-Instruct, any HF repo
Agent and memory settings
MAX_OUTPUT_TOKENS=2048
TEMPERATURE=0.7
MAX_DEPTH=5              # tree-depth cap (planner sets the adaptive value)
CHILDREN_PER_EXPANSION=3

MEMORY_FILE=memory.md    # shared cross-problem memory file (default: <repo>/memory.md)

Memory is enabled by default. Override the file per run with --memory-file <path>, or turn it off with --no-memory (both agent_main and math500_eval accept these flags).

vLLM KV-cache prefix optimization

Start vLLM with prefix caching, then run the convenience wrapper:

vllm serve Qwen/Qwen2.5-7B-Instruct --enable-prefix-caching
python run_math500_vllm.py --provider vllm --limit 100

The vLLM client structures prompts so the system message and problem context are identical across calls within a problem, so vLLM's automatic prefix caching reuses those KV entries.


πŸ—ΊοΈ Roadmap

  1. Plug-in task interface β€” a formal Task / Evaluator protocol so contributors can add GPQA and ARC without touching the agent.
  2. Embedding-based memory retrieval β€” replace keyword (Jaccard) overlap with semantic search.
  3. Bundle the LLM-judge eval so the paper's judged scores are reproducible from the repo.
  4. Docker image β€” zero-setup container with Ollama + ReTreVal + the UI pre-wired.

Follow along β€” and please share ideas β€” in Issues.


πŸ”— Related work

Tree-of-Thoughts Β· ReAct Β· Reflexion Β· Self-Refine

πŸ™ Thanks

ReTreVal stands on the shoulders of these wonderful projects β€” thank you to their authors and communities:

LangGraph Β· MATH-500 Β· Google Gemini Β· OpenAI Β· Ollama Β· vLLM Β· Next.js Β· React Flow.

Maintainers and contributors are listed in AUTHORS.md.


🀝 Contributing Β· ⭐ Star Β· πŸ“„ License

Contributions are very welcome β€” please see CONTRIBUTING.md to get started. The most helpful right now: new task evaluators (GPQA, ARC), the LLM-judge eval harness, and memory retrieval strategies. If ReTreVal is useful to you, a ⭐ would mean a lot β€” and thank you for taking a look.

Copyright 2026 QPIAI. Released under the Apache License 2.0.

About

Reasoning tree with validation

Resources

Contributing

Security policy

Stars

19 stars

Watchers

0 watching

Forks

Releases

Packages

Contributors

Languages