Document Q&A without a vector database — powered by PageIndex and any OpenAI-compatible LLM.
Traditional RAG pipelines embed every document chunk into a vector space and retrieve answers via cosine similarity search. PageIndex takes a fundamentally different approach:
| Aspect | Vector RAG | PageIndex Vectorless RAG |
|---|---|---|
| Storage | Embedding vectors + vector DB | Hierarchical JSON tree |
| Retrieval | Nearest-neighbour search | LLM-driven tree navigation |
| Context | Fixed-size chunks | Semantically coherent sections |
| Setup | Embedding model + vector DB required | Just an LLM — any provider |
| Accuracy (FinanceBench) | ~85–90 % | 98.7 % |
PageIndex converts a document into a smart table of contents — a hierarchical tree where each node represents a natural section. At query time, the LLM reasons through the tree (like a human expert scanning chapters) to find the most relevant sections, then generates a grounded answer.
git clone https://github.com/YOUR_USERNAME/pageindex-vectorless-rag.git
cd pageindex-vectorless-rag
python -m venv .venv
source .venv/bin/activate # Windows: .venv\Scripts\activate
pip install -r requirements.txt
pip install -e . # installs the pageindex-demo CLICopy the example environment file and edit it:
cp .env.example .envLLM_BASE_URL=http://localhost:1234/v1
LLM_API_KEY=lm-studio
LLM_MODEL=llama-3.1-8b-instructStart your local server, note the model name it reports at /v1/models, and set LLM_MODEL to match.
LLM_BASE_URL=https://api.openai.com/v1
LLM_API_KEY=sk-...
LLM_MODEL=gpt-4o-2024-11-20The project uses LiteLLM under the hood, so it supports 100+ providers out of the box:
# Anthropic
LLM_BASE_URL=https://api.anthropic.com
LLM_API_KEY=sk-ant-...
LLM_MODEL=anthropic/claude-sonnet-4-6
# Azure OpenAI
LLM_BASE_URL=https://YOUR_RESOURCE.openai.azure.com/openai/deployments/YOUR_DEPLOYMENT
LLM_API_KEY=YOUR_AZURE_KEY
LLM_MODEL=azure/gpt-4o
# Ollama
LLM_BASE_URL=http://localhost:11434/v1
LLM_API_KEY=ollama
LLM_MODEL=llama3.1# Check your configuration
pageindex-demo info
# Index a document (PDF or Markdown)
pageindex-demo index data/your_report.pdf
# Ask a single question
pageindex-demo ask data/your_report.pdf "What are the key findings?"
# Ask with sources
pageindex-demo ask data/your_report.pdf "Summarise chapter 3" --sources
# Interactive chat
pageindex-demo chat data/your_report.pdffrom pageindex_demo import RAGPipeline
pipeline = RAGPipeline()
# Index once — the tree is cached in results/
pipeline.load_document("report.pdf")
# Ask anything
answer = pipeline.ask("What are the main conclusions?")
print(answer)
# Ask with source attribution
result = pipeline.ask("What revenue was reported?", return_sources=True)
print(result["answer"])
for src in result["sources"]:
print(f" → {src['title']}")
# Interactive chat in the terminal
pipeline.chat()from pageindex_demo import RAGPipeline, Settings
settings = Settings(
llm_base_url="http://localhost:1234/v1",
llm_api_key="lm-studio",
llm_model="llama-3.1-8b-instruct",
max_pages_per_node=5,
max_tokens_per_node=10000,
)
pipeline = RAGPipeline(settings)
pipeline.load_document("report.pdf")
print(pipeline.ask("What is discussed in the introduction?"))pageindex-vectorless-rag/
├── src/
│ └── pageindex_demo/
│ ├── __init__.py # Public API exports
│ ├── config.py # Settings — env vars / .env file
│ ├── indexer.py # PDF / Markdown → PageIndex tree
│ ├── retriever.py # Vectorless tree-search via LLM
│ ├── pipeline.py # High-level RAG pipeline
│ └── cli.py # pageindex-demo CLI (Click)
├── examples/
│ ├── 01_index_document.py
│ ├── 02_query_rag.py
│ └── 03_interactive_chat.py
├── tests/
│ ├── conftest.py
│ └── test_pipeline.py
├── data/ # Put your PDFs here (gitignored)
├── results/ # Auto-generated index trees (gitignored)
├── .env.example # Configuration template
├── pyproject.toml # Package metadata (PEP 517/518)
└── requirements.txt
Usage: pageindex-demo [OPTIONS] COMMAND [ARGS]...
PageIndex Vectorless RAG — Q&A over documents without a vector database.
Options:
-v, --verbose Enable debug logging.
--help Show this message and exit.
Commands:
ask Ask a question about a document.
chat Interactive Q&A session.
index Build a PageIndex tree for a document.
info Show current configuration.
PDF / Markdown
│
▼
┌─────────────┐
│ PageIndex │ LLM reads the document, detects the table of contents,
│ Indexer │ and builds a hierarchical tree of sections/subsections.
└──────┬──────┘ Saved as JSON — no vectors, no embeddings.
│
▼ tree (JSON)
┌─────────────┐
│ Retriever │ LLM receives the tree skeleton + your query.
│ (tree │ It reasons about which nodes are relevant and
│ search) │ returns their IDs — like an expert scanning a ToC.
└──────┬──────┘
│ relevant node IDs
▼
┌─────────────┐
│ Answer │ Full text of the selected nodes is passed as context.
│ Generator │ LLM produces a grounded, cited answer.
└─────────────┘
│
▼
Final answer
| Variable | Default | Description |
|---|---|---|
LLM_BASE_URL |
https://api.openai.com/v1 |
LLM API endpoint |
LLM_API_KEY |
(required) | API key (use any string for local servers) |
LLM_MODEL |
gpt-4o-2024-11-20 |
Model name |
RETRIEVE_MODEL |
same as LLM_MODEL |
Model for tree-search step |
TOC_CHECK_PAGES |
20 |
Pages scanned for a table of contents |
MAX_PAGES_PER_NODE |
10 |
Max pages per index node |
MAX_TOKENS_PER_NODE |
20000 |
Token limit per node |
RESULTS_DIR |
results |
Output directory for cached trees |
pip install -r requirements-dev.txt
# Lint
ruff check src/ examples/ tests/
# Type-check
mypy src/
# Tests
pytest- Fork the repository
- Create a feature branch:
git checkout -b feat/your-feature - Commit your changes:
git commit -m "feat: add your feature" - Push and open a pull request
- PageIndex by VectifyAI — the vectorless RAG engine
- LiteLLM — unified LLM provider interface
- Click — CLI framework
MIT — see LICENSE.