Skip to content

Folders and files

NameName
Last commit message
Last commit date

Latest commit

 

History

7 Commits
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 

Repository files navigation

mem0-cpp

inspired by mem0 Apache 2.0 C++17 Qt 5/6

A C++17 implementation of the mem0 memory layer, built on Qt. Provides long-term fact-level memory for LLM applications — extract, deduplicate, store, and retrieve user context across conversations.

Overview

mem0-cpp reimplements the core architecture of mem0ai/mem0 (Apache 2.0) in C++ with Qt as the runtime framework. It is not a wrapper or binding — all core logic (fact extraction pipeline, hybrid retrieval, entity linking, storage) is a from-scratch C++ implementation designed for desktop and embedded environments where Python is unavailable.

Relationship to mem0 (Python)

Aspect mem0 (Python) mem0-cpp
Language Python C++17
Runtime Python + spaCy + OpenAI/Ollama Qt 5/6
Storage Qdrant / ChromaDB / etc. SQLite (WAL, FTS5)
NER spaCy statistical models Rule-based (regex + heuristics)
Parallelism asyncio QtConcurrent
Embedding OpenAI / Ollama HTTP Abstract IEmbeddingClient (inject any backend)
LLM OpenAI / Ollama HTTP Abstract ILLMClient (inject any backend)
Prompts Ported from mem0/configs/prompts.py Ported verbatim
Scoring Graph-based + BM25 Cosine + sigmoid-normalized BM25 + entity boost

The extraction prompts are direct ports of mem0's ADDITIVE_EXTRACTION_PROMPT (v3) and DEFAULT_UPDATE_MEMORY_PROMPT (v1). The scoring pipeline preserves the original's three-signal fusion (semantic + keyword + entity) with C++ implementations of sigmoid BM25 normalization and cosine similarity.

Architecture

flowchart LR
    subgraph Input
        M[Messages]
    end

    subgraph mem0-cpp
        direction TB
        E[LLM Fact Extraction] --> D[SHA-256 Dedup]
        D --> S[SQLite Storage]
        S --> R[Hybrid Retrieval]
        R --> CS[Cosine Similarity]
        R --> BM25[FTS5 BM25]
        R --> EN[Entity Boost]
        CS --> F[Score Fusion]
        BM25 --> F
        EN --> F
        EL[EntityLinker] --> EN
    end

    subgraph External - inject via interfaces
        LLM[ILLMClient]
        EMB[IEmbeddingClient]
    end

    M --> E
    LLM --> E
    EMB --> S
    EMB --> EL
Loading

Core Components

Component File Description
Mem0 src/mem0.h/.cpp Main orchestrator: extract → embed → dedup → store → retrieve
Storage src/storage.h/.cpp SQLite unified storage (embeddings, FTS5, entities, history)
EntityLinker src/entitylinker.h/.cpp Rule-based NER + entity-memory linking
Scoring src/scoring.h/.cpp Sigmoid BM25 normalization, cosine similarity
Prompts src/prompts.h/.cpp Fact extraction prompts (ported from mem0)
Utils src/utils.h/.cpp SHA-256 hashing, vector serialization, text utilities
Interfaces src/interfaces.h ILLMClient / IEmbeddingClient abstract adapters

Quick Start

Build

# Prerequisites: Qt 5.15+ or Qt 6, CMake 3.16+
mkdir build && cd build
cmake .. -DCMAKE_PREFIX_PATH=/path/to/Qt
make -j$(nproc)

Usage

#include <mem0.h>
#include <interfaces.h>

// 1. Implement abstract interfaces
class MyLLMClient : public mem0::ILLMClient {
    QString generate(const QList<QPair<QString, QString>> &messages,
                     bool jsonMode) override;
};

class MyEmbeddingClient : public mem0::IEmbeddingClient {
    QVector<float> embed(const QString &text) override;
    QList<QVector<float>> embedBatch(const QStringList &texts) override;
    int dimension() const override;
};

// 2. Create Mem0 instance
mem0::Mem0::Config config;
config.dbPath = "/path/to/mem0.db";

mem0::Mem0 m(new MyLLMClient(), new MyEmbeddingClient(), config);  // tables created in constructor

// 3. Add memories from a conversation
QList<mem0::Message> messages = {{"user", "I work at UnionTech"}, {"assistant", "Great!"}};
auto results = m.add(messages, "user_42");
// results: [{id: "uuid", memory: "User works at UnionTech", event: "ADD"}]

// 4. Search with hybrid retrieval
auto searchResults = m.search("What does the user do for a living?", "user_42");
// returns ranked memories with fused scores

As a CMake Dependency

# In your project's CMakeLists.txt
add_subdirectory(path/to/mem0-cpp)
target_link_libraries(your_target mem0)

Outputs a static library libmem0.a (or mem0.lib on Windows).

API Reference

Mem0

Method Description
add(messages, userId) Extract facts from messages, dedup, store
add(text, userId) Convenience overload for single text
addBatch(batch, userId) Parallel extraction across multiple conversations
search(query, userId, topK, threshold) Hybrid retrieval: semantic + BM25 + entity boost
getAll(userId, topK) List all memories for a user
update(memoryId, text) Update a memory's text and re-embed
remove(memoryId) Delete a single memory
removeAll(userId) Delete all memories for a user
history(memoryId) Get change history for a memory

ILLMClient (implement)

Method Description
generate(messages, jsonMode) Send chat messages, return text response

IEmbeddingClient (implement)

Method Description
embed(text) Single text → vector
embedBatch(texts) Multiple texts → vectors
dimension() Vector dimension

Testing

cd build
make
./test_mem0        # 28 tests, ~200ms
ctest --output-on-failure

Tests use mock LLM/embedding clients (no external services required).

Design Decisions

  • SQLite-only storage: No external vector database dependency. Embeddings are stored as BLOBs in SQLite with WAL mode. FTS5 handles keyword retrieval. Suitable for single-user desktop applications with moderate memory counts.
  • Dependency injection via abstract interfaces: ILLMClient and IEmbeddingClient are pure virtual. Wire in any backend — local models, HTTP APIs, D-Bus services.
  • Rule-based NER instead of spaCy: Desktop applications typically cannot ship spaCy models. The EntityLinker uses regex-based extraction for four entity types (PROPER, QUOTED, TOPIC, IDENTIFIER) with embedding-based semantic matching for disambiguation.
  • SHA-256 for dedup: Text content is hashed with SHA-256 before storage. Existing hashes are queried via lightweight SQL to avoid full record loading.

Requirements

  • Qt 5.15+ or Qt 6.x (Core, Sql, Concurrent modules)
  • CMake 3.16+
  • C++17 compiler

Optional: Qt Network module (for the built-in LLMClient HTTP implementation)

License

Apache License 2.0 — see LICENSE.

This project reuses extraction prompts from mem0ai/mem0 (Apache 2.0). The C++ implementation is an independent reimplementation, not derived from the Python source code.

About

a from-scratch C++17/Qt port of mem0 — a memory layer for AI assistants. Extracts facts from conversations, stores them in SQLite with FTS5, and retrieves via hybrid semantic + BM25 + entity-boosted search. No Python dependencies.

Topics

Resources

Contributing

Stars

1 star

Watchers

0 watching

Forks

Releases

Packages

Contributors

Languages