How to Integrate OmniRoute's Memory System with FTS5 and Vector Quantization

OmniRoute combines SQLite FTS5 virtual tables for full-text search and scalable vector quantization to store compressed embeddings, enabling fast hybrid retrieval across textual and semantic queries.

The open-source OmniRoute repository (diegosouzapw/OmniRoute) provides a conversational memory layer that stores "memories" in SQLite and optionally off-loads vectors to Qdrant. By integrating FTS5 for keyword search and vector quantization for efficient embedding storage, you can significantly improve retrieval speed while reducing disk usage.

Understanding OmniRoute's Dual Retrieval Architecture

OmniRoute maintains conversational context through two complementary indexing strategies: lexical search via FTS5 and semantic search via vector stores. These systems operate independently but can be queried together for hybrid retrieval.

Full-Text Search with FTS5

The memory system uses SQLite's native FTS5 extension to create a virtual table mapped to the memories table. This is implemented in migration 022_add_memory_fts5.sql, which creates the memories_fts virtual table and indexes the content column.

When enabled, textual insertions automatically populate both the base memories table and the FTS5 index, allowing you to run high-performance MATCH queries without scanning full table rows.

Vector Storage Options

OmniRoute supports three storage backends controlled by the memoryVectorStore setting in src/lib/memory/settings.ts:

  • "sqlite-vec" (default): Embeddings stored in SQLite using the sqlite-vec extension
  • "qdrant": Off-loads vectors to an external Qdrant collection
  • "auto": Currently defaults to SQLite

The active configuration is persisted via src/lib/db/memoryVec.ts and can be modified through the Settings API or CLI.

Configuring FTS5 for Memory Content

To enable full-text search capabilities, you must apply the FTS5 migration. This creates the virtual table that shadows your existing memories.

Run the migration using the provided npm script:

npm run migration:run

This executes 022_add_memory_fts5.sql, creating the memories_fts virtual table. Once applied, every new memory automatically generates an FTS5 entry alongside the base record.

To search memories using FTS5, query the virtual table with the MATCH operator:

import { getDbInstance } from '../../src/lib/db/core.js';

const db = getDbInstance();
const rows = db.prepare(`
  SELECT id, content FROM memories_fts WHERE content MATCH ?
`).all('quantum computing');

Implementing Vector Quantization

Quantization reduces embedding precision from 32-bit floats to 8-bit integers (or binary), cutting storage by 75% while preserving retrieval quality. OmniRoute handles quantization differently depending on your selected vector store.

SQLite-vec Quantization Modes

For the SQLite backend, quantization is controlled via the MEMORY_VEC_QUANTIZATION environment variable. Set this in your .env file or shell:

MEMORY_VEC_QUANTIZATION=int8   # Options: "none", "int8", "binary"

The quantization logic resides in src/lib/memory/vectorStore.ts. When int8 is selected, the SQL placeholder is dynamically swapped for vec_quantize_int8(?, 'unit') during insertion. Binary quantization uses a similar mechanism for extreme compression.

Qdrant Quantization Configuration

When using Qdrant, quantization is configured via the qdrantQuantization field in the memory settings. Valid values are "none", "int8", or "binary".

The helper function buildQuantizationConfig in src/lib/memory/qdrant.ts constructs the appropriate collection configuration. For quantized collections, it automatically enables rescore: true to maintain search accuracy:

// Update settings via the Settings API
await fetch('http://localhost:3000/api/settings/memory', {
  method: 'PATCH',
  headers: { 'Content-Type': 'application/json' },
  body: JSON.stringify({
    memoryVectorStore: 'qdrant',
    qdrantQuantization: 'int8'
  })
});

Re-indexing Memories After Configuration Changes

Changing quantization modes invalidates existing embeddings. You must re-index stored memories to apply new precision settings.

Flag all existing memories for re-indexing using the markAllMemoriesNeedReindex function in src/lib/db/memoryVec.ts:

import { markAllMemoriesNeedReindex } from '../../src/lib/db/memoryVec.js';

const affected = markAllMemoriesNeedReindex();
console.log(`Marked ${affected} memories for re-index`);

The background re-indexer (open‑sse/services/memoryReindex.ts) processes the queue via getMemoryReindexQueue, regenerating embeddings with the new quantization settings. Run this service after changing any quantization configuration.

End-to-End Usage Examples

Once configured, you can interact with the memory system through CLI tools or HTTP endpoints.

Inserting Memories

Add content via the CLI:

omniroute memory add \
  --content "Explain quantum computing in simple terms." \
  --key "quantum-explain"

Or use the HTTP endpoint:

curl -X POST http://localhost:3000/api/memory \
  -H "Content-Type: application/json" \
  -d '{"content": "Explain quantum computing.", "key": "quantum"}'

Both methods write text to the FTS5 index and store quantized embeddings in your configured vector store.

Hybrid Search Queries

Perform full-text searches against the FTS5 virtual table for keyword matches:

const results = db.prepare(`
  SELECT id, content FROM memories_fts WHERE content MATCH ?
`).all('simple terms');

For semantic similarity, use the vector search endpoint:

const response = await fetch('http://localhost:3000/api/memory/search', {
  method: 'POST',
  headers: { 'Content-Type': 'application/json' },
  body: JSON.stringify({ query: 'What is a qubit?' })
});
const semanticResults = await response.json();

Summary

  • FTS5 Integration: Migration 022_add_memory_fts5.sql creates a virtual table enabling fast keyword search through SQLite's native MATCH syntax.
  • Vector Quantization: Reduce storage by setting MEMORY_VEC_QUANTIZATION (SQLite) or qdrantQuantization (Qdrant) to "int8" or "binary".
  • Storage Backends: Choose between "sqlite-vec" for local SQLite storage or "qdrant" for external vector databases via memoryVectorStore settings.
  • Re-indexing Required: Always run markAllMemoriesNeedReindex() after changing quantization modes to update existing embeddings.
  • Key Files: Core logic resides in src/lib/memory/vectorStore.ts (SQLite quantization), src/lib/memory/qdrant.ts (Qdrant config), and src/lib/db/memoryVec.ts (settings persistence).

Frequently Asked Questions

What file enables FTS5 search in OmniRoute?

The migration file src/lib/db/migrations/022_add_memory_fts5.sql creates the FTS5 virtual table named memories_fts. This file adds the full-text index on the content column of the memories table, allowing SQLite to perform optimized keyword searches using the MATCH operator.

How do I switch from float32 to int8 quantization in SQLite?

Set the environment variable MEMORY_VEC_QUANTIZATION=int8 before starting the application. This triggers the logic in src/lib/memory/vectorStore.ts to wrap SQL placeholders with vec_quantize_int8(?, 'unit') during insertion, automatically converting 32-bit float embeddings to 8-bit integers.

Why must I re-index memories after changing quantization settings?

Existing embeddings were computed and stored using the previous precision format (e.g., float32). When you switch to int8 or binary, the stored vectors become incompatible with the new search parameters. The markAllMemoriesNeedReindex() function flags all rows for regeneration, ensuring the background re-indexer in open‑sse/services/memoryReindex.ts recalculates embeddings with the correct quantization.

Can I use both FTS5 and vector quantization simultaneously?

Yes. FTS5 handles lexical search on text content, while vector quantization optimizes the storage of semantic embeddings. Configure FTS5 via the migration and quantization via MEMORY_VEC_QUANTIZATION (SQLite) or qdrantQuantization (Qdrant). The systems are orthogonal—FTS5 does not affect vector storage and vice versa.

Have a question about this repo?

These articles cover the highlights, but your codebase questions are specific. Give your agent direct access to the source. Share this with your agent to get started:

Share the following with your agent to get started:
curl -s "https://instagit.com/install.md"

Works with
Claude Codex Cursor VS Code OpenClaw Any MCP Client

Maintain an open-source project? Get it listed too →