All Projects

Infrastructure2026

Compact Hierarchical Memory Engine (CHME)

CHME, Compact Hierarchical Memory Engine (CHME), is an in-memory memory orchestration engine that provides multi-collection support, keyword-based retrieval, automatic routing, and snapshot persistence for LLM applications. It features deterministic behavior and supports both local (Ollama) and cloud (OpenAI-compatible) providers. Made with curiosity, not complexity. It may not have achieved significant success, but it made sense as a concept. The project also includes a technical paper outlining the architectural approach, along with benchmark results and detailed technical infrastructure documentation.

LLM Memory ManagementLLM ApplicationsIn-Memory ComputingPersistenceDeterministic SystemsNode.jsTypeScript

Compact Hierarchical Memory Engine (CHME)

CHME is a compact, in-memory, hierarchical memory orchestration engine written in TypeScript. It provides a structured memory system for Large Language Models (LLM) and automatically extracts, indexes, and queries information from markdown-based documents.

Core Flow

1. ingest / ingestAuto     → Markdown to document/section/chunk tree
2. keyword index build      → Chunk-level indexing
3. scoped or global ask   → Query with automatic routing
4. optional snapshot save  → Fast restart with .chme.json.gz persistence

Key Features

FeatureDescription
Multi-Collection SupportManages multiple topic domains in isolated collections
Auto-RoutingRoutes queries to correct collections via regex-based rules
Keyword IndexingSection-aware chunk-level search
Local LLM SupportOllama integration for local inference
Cloud LLM SupportOpenAI-compatible APIs (Mistral, OpenAI, etc.)
Snapshot PersistenceCompressed state saving in .chme.json.gz format
Deterministic BehaviorReproducible routing, retrieval, and prompt generation

Installation

npm install

Quick Start

import { MemoryEngine } from './src/MemoryEngine'

async function main() {
  const engine = new MemoryEngine({
    provider: 'local',
    model: 'qwen2.5:7b',
    snapshotDir: './snapshots'
  })

  // Auto-ingest markdown files into collections
  await engine.ingestAuto('./test', { defaultCollectionId: 'general' })
  
  // Save snapshots for fast restart
  await engine.saveSnapshots()

  // Ask questions without specifying collection
  const answer = await engine.ask('What is the main topic of the files?')
  console.log(answer)
}

main().catch(console.error)

Supported Providers

Local (Ollama)

const engine = new MemoryEngine({
  provider: 'local',
  localUrl: 'http://localhost:11434/api/generate',
  model: 'qwen2.5:7b',
  temperature: 0
})

OpenAI-Compatible (Mistral, etc.)

const engine = new MemoryEngine({
  provider: 'openai',
  model: 'mistral-small-latest',
  openAIBaseUrl: 'https://api.mistral.ai/v1',
  openAIApiKey: process.env.MISTRAL_API_KEY,
  temperature: 0
})

Available Scripts

# Unit + integration tests (including snapshot flow)
npm run verify

# Dry-run without Ollama
npm run test:ollama:dry

# Live Ollama test (qwen2.5:7b)
npm run test:ollama

# Basic pipeline smoke run
npm run pipeline

# Benchmark tests
npm run benchmark           # Deterministic benchmark
npm run benchmark:factual   # Factual accuracy benchmark
npm run benchmark:live     # Live LLM benchmark
npm run benchmark:factual:live  # Live factual grading
npm run benchmark:factual:mistral  # Mistral factual benchmark

Architecture

┌─────────────────────────────────────────────────────────────────┐
│                        MemoryEngine                              │
│                    (Main Entry Point)                            │
├─────────────────────────────────────────────────────────────────┤
│  ┌──────────────┐  ┌──────────────┐  ┌──────────────────────┐  │
│  │   Ingest    │  │    Query     │  │   GenerateAnswer     │  │
│  │   Module    │  │    Module    │  │      Module           │  │
│  └──────────────┘  └──────────────┘  └──────────────────────┘  │
│         │                 │                      │               │
│         ▼                 ▼                      ▼               │
│  ┌─────────────────────────────────────────────────────────────┐ │
│  │                    Collection Management                    │ │
│  │  ┌─────────┐  ┌─────────┐  ┌─────────┐  ┌─────────────┐   │ │
│  │  │Documents│  │ Sections│  │  Chunks │  │    Nodes    │   │ │
│  │  └─────────┘  └─────────┘  └─────────┘  └─────────────┘   │ │
│  └─────────────────────────────────────────────────────────────┘ │
│         │                 │                      │               │
│         ▼                 ▼                      ▼               │
│  ┌─────────────────────────────────────────────────────────────┐ │
│  │                    Keyword Index                             │ │
│  │              (Chunk → Document Mapping)                     │ │
│  └─────────────────────────────────────────────────────────────┘ │
└─────────────────────────────────────────────────────────────────┘
                               │
                               ▼
         ┌─────────────────────────────────────────────┐
         │              LLM Integration                │
         │  ┌─────────────┐    ┌───────────────────┐   │
         │  │   Ollama    │    │ OpenAI-compatible │   │
         │  │  (Local)   │    │  API (Mistral)    │   │
         │  └─────────────┘    └───────────────────┘   │
         └─────────────────────────────────────────────┘

Data Model

Collection Hierarchy

Collection
├── id: string
├── documents: Document[]
├── sections: Section[]
├── chunks: Chunk[]
├── nodes: Node[]
└── keywords: Map<string, number>

Document Flow

Markdown File
       │
       ▼
   Document
       │
       ├── Section 1 ───┬──▶ Chunk 1 ──▶ Node 1
       │                ├──▶ Chunk 2 ──▶ Node 2
       │                └──▶ Chunk 3 ──▶ Node 3
       │
       ├── Section 2 ───┬──▶ Chunk 4 ──▶ Node 4
       │                └──▶ Chunk 5 ──▶ Node 5
       │
       └── Section N ──▶ ...

Node ID Schema

LevelFormatExample
Root{docId}:rootoverview:root
Section{docId}:section:{sectionIndex}overview:section:1
Chunk{docId}:{sectionIndex}:{chunkIndex}overview:1:0

Configuration

MemoryEngine Options

OptionTypeDefaultDescription
modelstringqwen2.5:7bLLM model name
topKnumber5Default top-K chunks per collection
maxContextCharsnumber2000Maximum context characters
temperaturenumber0LLM temperature
maxTokensnumber-Maximum tokens for generation
provider'local' | 'openai''local'LLM provider
localUrlstringhttp://localhost:11434/api/generateOllama endpoint
openAIBaseUrlstring-OpenAI-compatible API URL
openAIApiKeystring-API key
snapshotDirstring./snapshotsSnapshot directory

Benchmark Results

Dataset

CollectionDocumentsSectionsChunksNodesKeywords
compliance5305085206
payments5305085215
risk5305085201

Performance Metrics

MetricScore
Route Top-1 Accuracy1.00
Route Recall@N1.00
Hit@K0.917
MRR@K0.799
Evidence Recall0.819
Mean Factual Score0.546

Latency Profile

StageMean (ms)P50 (ms)P95 (ms)
Route0.050.040.08
Retrieve0.09-0.350.09-0.250.15-0.67
Prompt0.070.060.15
Ask (LLM)~6025~5674~10511

Note: Memory pipeline stages are sub-millisecond to low-millisecond. End-to-end latency is dominated by external model inference.

Determinism

  • Route determinism: ✅ 100%
  • Retrieve determinism: ✅ 100%
  • Prompt determinism: ✅ 100%
  • Snapshot roundtrip: ✅ Pass (0 mismatches)

Snapshot System

Save Snapshots

await engine.saveSnapshots('./snapshots')
// Creates: 
// - snapshots/_engine.chme.json.gz
// - snapshots/<collectionId>.chme.json.gz

Load Snapshots

await engine.loadSnapshots('./snapshots', {
  sourceRootPath: './knowledge'  // Optional: freshness check
})

Warm Startup Pattern

import { existsSync } from 'node:fs'
import { MemoryEngine } from './src/MemoryEngine'

async function bootstrap() {
  const sourceRoot = './knowledge'
  const snapshotDir = './snapshots'

  const engine = new MemoryEngine({
    provider: 'local',
    model: 'qwen2.5:7b',
    temperature: 0
  })

  if (existsSync(`${snapshotDir}/_engine.chme.json.gz`)) {
    // Load existing snapshots (with optional freshness check)
    await engine.loadSnapshots(snapshotDir, { sourceRootPath: sourceRoot })
  } else {
    // Fresh start - ingest and save
    await engine.ingestAuto(sourceRoot, { defaultCollectionId: 'general' })
    await engine.saveSnapshots(snapshotDir)
  }

  return engine
}

Routing Rules

Configure automatic collection assignment during ingestion:

engine.setRoutingRules([
  { pattern: /faq/i, collectionId: 'faq', priority: 10 },
  { pattern: /release/i, collectionId: 'release_notes', priority: 5 },
  { pattern: /^ops\//, collectionId: 'operations', priority: 8 }
])

await engine.ingestAuto('./knowledge', { defaultCollectionId: 'general' })

Routing Priority:

  1. Rule match (higher priority first)
  2. Path-based slug (first folder)
  3. Default collection

Global vs Scoped Ask

Global Ask (auto-routing)

const answer = await engine.ask('What is the main topic?', {
  topCollections: 3,
  topKPerCollection: 3,
  maxContextChars: 2000
})

Use when:

  • User doesn't know the right collection
  • Multi-domain knowledge base
  • Top-N collection routing needed

Scoped Ask (specific collection)

const answer = await engine.ask('product_docs', 'How does ingestion work?')

Use when:

  • Question belongs to one known domain
  • Tighter retrieval control needed
  • UI already selects a collection

Debugging Tools

// Debug routing
const collections = await engine.routeCollections('How does keyword retrieval work?', { topCollections: 3 })
console.log('Routed:', collections)

// Debug retrieval
const chunks = await engine.retrieve(collections[0], 'How does keyword retrieval work?', 5)
console.log(chunks.map((c) => c.id))

// Debug prompt
const prompt = await engine.buildPrompt(collections[0], 'How does keyword retrieval work?', 5, 1200)
console.log(prompt)

Documentation

DocumentDescription
SYSTEM_DESIGN.mdDetailed system architecture and algorithms
eng_usage.mdComplete English usage guide
usage.mdTurkish usage guide
MEMORY_ENGINE_STATUS.mdCurrent status and capabilities
benchmark/README.mdBenchmark documentation

Future Work

  • Multi-lingual support
  • Response caching
  • Learned rerankers

Version: 1.0.0
Last Updated: 2026-02-26

Roadmap & Improvement Areas

We are actively working on improving CHME. Current focus areas include:

1. Reranking Strategy

A reranking layer is planned to improve retrieval precision. The current keyword-based retrieval provides fast candidate generation, but a learned reranker will help filter and rank the most relevant chunks before context construction.

2. Factual Accuracy Improvement

Current factual accuracy: 0.546 - 0.59
Target: 0.80+

Key improvements planned:

  • Hybrid retrieval (keyword + semantic embeddings)
  • Better chunk boundary detection
  • Improved prompt engineering
  • Enhanced evidence coverage metrics
Technologies
Node.jsTypeScriptIn-Memory ComputingLLM Memory Management