Roadmap
What v0.1.0 ships, where it is not generic today, and the two directions in which the next iterations can extend it. Both directions are independent and can land in either order.
Where v0.1.0 stands
| Layer | Generic ? | Notes |
|---|---|---|
Codec TPgVector (text + binary) |
✅ | float32 vectors, no notion of source language |
| Embedding clients (Ollama, transport stack) | ✅ | text in, vector out |
| LLM clients | ✅ | text in, text out |
CLI harness mormot.ai.cli |
✅ | argv parser, framework-free |
Vector backend (IVectorBackend) |
✅ | abstracted in v0.1.0 → see feat/sqlite-backend |
Chunker mormot.ai.chunk |
❌ | walks .pas / .pp / .dpr / .inc only, parses Pascal top-level declarations, derives mORMot families from src/<family>/... |
Schema mormot_chunks |
❌ | columns unit_name, family, symbol, kind, line_start, line_end are Pascal/mORMot-shaped |
| Orchestrator ingest path | ❌ | hard-wired to ChunkerDecompose and the Pascal-shaped schema |
CLI programs (01_ingest_mormot2, 02_query_cli, 03_chat_cli) |
❌ | RAG prompts and flag wording assume mORMot 2 source |
Roughly 60 % of the code is content-agnostic. The remaining 40 % (chunker, schema, ingest, CLIs) is Pascal/mORMot-specific by design — v0.1.0 is the “RAG on mORMot 2 source” deliverable.
TODO 1 — Multi-store backend (feat/sqlite-backend)
Status: branch open; IVectorBackend interface extracted in commit
ae42cff. TPgvectorBackend ships as the reference implementation.
2 665 / 2 665 unit tests pass through the interface boundary.
What is left to deliver an SQLite target:
- Choose the SQLite extension. Two viable options, both modern:
sqlite-vec(Alex Garcia, Apache-2.0). Vector-only, no FTS — combine with SQLite's built-in FTS5 for the hybrid score.sqlite-vss(older sibling, wraps Faiss). Less actively maintained as of late 2025.- Implement
TSqliteVecBackend: IVectorBackendinsrc/mormot.db.sqlite.vec.pas: SchemaSql→CREATE VIRTUAL TABLE ... USING vec0(...)for the vector half +CREATE VIRTUAL TABLE ... USING fts5(...)for the text half.IngestInsertSql→ twoINSERTstatements (vec0 + fts5) wrapped in a transaction at the orchestrator level, OR a single materializedmormot_chunkstable joined to the two virtual tables onrowid.HybridSelectSql→vec_distance_cosine(...)+ FTS5bm25(...)instead of<=>+ts_rank_cd. Theαblend stays identical.BindEmbedding→ raw float32 little-endian BLOB (no header, no cast required — sqlite-vec's wire format is the simplest possible).- Tests: parallel-structure regression suite gated on
MORMOT2_PGVECTOR_SQLITE_DB(or similar). Reuse the existing live-test fixtures via the orchestrator, not the backend. - Docs: add a “Choosing a backend” page to
docs/configuration.mdsummarizing trade-offs (PG: bigger, faster HNSW, requires server; SQLite: single-file, embedded, simpler ops).
Effort estimate: 6 – 8 hours (mechanical port; the IVectorBackend contract is fully specified).
TODO 2 — Multi-source chunker (feat/generic-chunker)
Status: not started. The current chunker is one Pascal-shaped implementation with no interface around it.
What it would take to ingest non-Pascal sources (Markdown, plain text, PDF, JSONL, …):
- Extract
IChunkerinsrc/mormot.ai.chunk.backend.pas:IChunker = interface /// chunk a single source (file path, raw text, stream) function Chunk(const Source: RawUtf8): TChunkDynArray; /// declare which paths/extensions this chunker recognizes function Handles(const Path: RawUtf8): boolean; /// short backend name for diagnostics function Name: RawUtf8; end; - Generic chunk record to replace the Pascal-shaped
TPascalChunk:TGenericChunk = record SourceId: RawUtf8; // file path or URL or doc id SectionId: RawUtf8; // page #, anchor, line range, ... Content: RawUtf8; Tokens: integer; Metadata: variant; // free-form JSON for backend-specific fields end; - Generic schema
vector_chunks(id BIGSERIAL, source_id TEXT, section_id TEXT, content TEXT, embedding VECTOR(N), ts TSVECTOR, metadata JSONB, created_at TIMESTAMPTZ). The Pascal-shaped fields (unit_name,family,symbol,kind,line_start,line_end) land inmetadatafor the Pascal chunker's output, where the retrieval SQL can still filter on them viametadata->>'family'. - Concrete implementations:
TPascalChunker(rename of the current chunker; populatesmetadatawith the existing Pascal fields)TMarkdownChunker(split on heading levels, respect token caps, attach the heading path tosection_id)TPlainTextChunker(sliding window N tokens, overlap M)TJsonlChunker(one line = one chunk,metadatafrom the JSON fields)- Optional later:
TPdfChunker(via mORMot's PDF reader or an external binary),TTreeSitterChunker(multi-language code). - Orchestrator changes:
Ingest(SrcRoot, Chunker)— chunker decides what to walk and how.- The bulk-insert path becomes generic too.
- CLI changes:
01_ingest_mormot2becomes01_ingest --chunker pascal --src ...withpascalas the default for back-compat.02_query_cliand03_chat_clino longer hard-code mORMot wording in prompts; the RAG prompt template moves to a flag / env var.
Effort estimate: ~10 hours including tests for two chunkers (Pascal + Markdown) plus the schema migration.
Other ideas (post-v0.2)
- Incremental re-embedding driven by
git diff. Only re-embed files that changed since the last ingest; mark old chunks deleted in a soft-delete column. - Sparse retrieval (BM25-only or learned-sparse like SPLADE) to complement the dense vector half.
- Reranker pass (cross-encoder via Ollama) after the top-K hybrid retrieval, for a higher-quality top-3.
- Tree-sitter chunkers for non-Pascal source code (Go, Rust, Python,
TS) via the
tree-sitterC library through mORMot's FFI. - Per-tenant isolation (one schema per tenant or a
tenant_idfilter on every query) for multi-customer deployments. - Vector quantization (PQ / SQ via pgvector 0.8+ or sqlite-vec) to shrink the index footprint at large corpus sizes.
How to follow along
feat/sqlite-backendbranch — the current iteration on TODO 1.- A
feat/generic-chunkerbranch will open when TODO 2 starts. - Each branch keeps
maingreen: theTPgvectorBackendand Pascal chunker remain the v0.1.0 reference until a v0.2.0 cut.