tivins / llm-memory
Semantic memory store for LLM applications — embed, store, recall via pgvector.
0.4.0
2026-06-21 16:21 UTC
Requires
- php: ^8.3
- ext-pdo: *
- ext-pgsql: *
- tivins/llm-lib: ^0.5
- tivins/pdow: ^0.1
- tivins/php-core: ^2.0
Requires (Dev)
- phpunit/phpunit: ^11.5
README
Semantic memory store for LLM applications — embed, store, and recall text fragments via pgvector.
Overview
A PHP library that provides a RAG-style retrieval pipeline:
- Store text fragments in PostgreSQL + pgvector with automatic embedding.
- Recall relevant fragments using a two-stage pipeline: vector ANN search → cross-encoder reranking.
- Deduplicate entries via SHA-256 content hashing per collection.
Requirements
- PHP 8.3+
- PostgreSQL with pgvector
- llama.cpp embedding server (port 8081, e.g.
bge-m3) - llama.cpp rerank server (port 8082, e.g.
Qwen3-Reranker) — optional
Installation
composer require tivins/llm-memory
Quick start
use Tivins\LlmLib\LLM; use Tivins\LlmMemory\MemoryStore; use Tivins\Pdow\Database; $db = Database::connect('pgsql:host=127.0.0.1;dbname=memory_project', 'user', 'pass'); $embedder = new LLM('http://127.0.0.1:8081', defaultModel: 'bge-m3-Q8_0.gguf'); $reranker = new LLM('http://127.0.0.1:8082', defaultModel: 'Qwen3-Reranker-4B-Q4_K_M.gguf'); $memory = new MemoryStore($db, $embedder, $reranker); $memory->migrate(); $memory->ensureCollection('user:42', 'bge-m3-Q8_0.gguf', 1024); // Store $memory->remember('user:42', 'Marie is allergic to peanuts.', kind: 'fact'); // Recall $results = $memory->recall('user:42', 'What foods should Marie avoid?', topN: 3); foreach ($results as $hit) { echo $hit->entry->content . ' (score: ' . $hit->rerankScore . ")\n"; } // Forget $memory->forgetInCollection('user:42', $entryId); $memory->forgetCollection('user:42');
Agent integration
Wire memory tools into an llm-lib agent:
use Tivins\LlmLib\Agent; use Tivins\LlmLib\ToolRegistry; use Tivins\LlmMemory\Tools\MemoryTools; $memoryTools = new MemoryTools($memory, collection: 'user:42'); $agent = new Agent($chatLlm, new ToolRegistry(...$memoryTools->all())); $result = $agent->runTurn($conversation, $options);
Collections are typically namespaced (user:{id}, {app}:{scope}). See examples/agent.php for a full runnable demo.
API
| Method | Description |
|---|---|
ensureCollection(id, model, dim) |
Create a collection if it doesn't exist |
remember(collection, content, kind?, metadata?) |
Store a text fragment (embeds automatically, deduplicates) |
rememberMany(collection, items) |
Batch store — one embedding call for N fragments |
recall(collection, query, topN?, annTopK?, minRerankScore?) |
Retrieve relevant entries (ANN + optional rerank) |
recallAnnOnly(collection, query, topN?) |
ANN search only — skips rerank even when a reranker is configured |
listEntries(collection, limit?, offset?, idFrom?, idTo?) |
List entries (latest N or ID range) |
getById(id) |
Fetch a single entry by ID |
forget(id) |
Soft-delete a single entry (any collection) |
forgetInCollection(collection, id) |
Soft-delete within a collection; returns false if not found |
forgetCollection(id) |
Soft-delete all entries in a collection |
count(collection) |
Count active entries in a collection |
migrate() |
Run SQL migrations |
Testing
composer test
Integration tests require PostgreSQL with pgvector (see install.md). Unit tests for DTOs run without a database. Embedding/rerank calls use StubLLM from llm-lib — no llama.cpp server needed.
Dependencies
| Package | Role |
|---|---|
| tivins/llm-lib | Embedding & rerank HTTP clients |
| tivins/pdow | PDO database wrapper |
License
MIT.