Files
pi-qmem/gateway
enne2 86ac1996fb feat(private): memorie riservate escluse dalle ricerche standard
- gateway: campo private (bool) in MemoryIn; filtro must_not private=true
  di default in search_filter; include_private in SearchIn per ricerche
  esplicite; campo private esposto in format_results
- estensione: parametro private in qmem_store, include_private in qmem_search
  (con descrizioni e avvertenze sui prompt dei modelli)
- testato su brain: record private invisibile alla ricerca standard,
  visibile solo con include_private=true; topic esplicito da solo non sblocca
- deploy: /opt/memory/gateway ricostruito (container memory-gateway)
2026-08-25 20:14:28 +02:00
..

Memory Gateway — deploy

Componente server di pi-qmem: FastAPI + Qdrant 1.19 + Ollama (BGE-M3). Nessun LLM in scrittura: l'agente salva record deliberati e strutturati.

pi (estensione pi-qmem) ──HTTPS/VPN──▶ Memory Gateway (FastAPI:8082) ──▶ Qdrant 1.19 (6333)
                                              │
                                              └──▶ Ollama BGE-M3 (11434, nativo host)

Deploy (Docker Compose)

# 1. Prepara l'ambiente (vedi qmem-gateway/docker-compose.yml come riferimento)
cp .env.example .env
chmod 600 .env
# genera le chiavi:
#   QDRANT_ADMIN_API_KEY=$(openssl rand -hex 32)
#   QDRANT_READ_ONLY_API_KEY=$(openssl rand -hex 32)
#   API_KEYS=$(openssl rand -hex 32)   # chiave condivisa per gli agenti

# 2. Avvia
docker compose up -d --build

# 3. Verifica
curl http://127.0.0.1:8082/v1/status

Requisiti: Docker + Compose v2, Ollama con modello bge-m3 sul host (ollama pull bge-m3), porta 8082 libera sull'interfaccia VPN.

API

Endpoint Descrizione
POST /v1/memories Crea record (text, kind, agent_id, scope, project_id obbligatorio, source, expires_at, supersedes_id, supersede_reason). Applica il guardrail di similarità pre-scrittura
POST /v1/memories:search Ricerca semantica (query, kind, project_id, scope, top_k, include_superseded, min_score)
GET /v1/memories/{id} Recupera per UUID
DELETE /v1/memories/{id} Elimina per UUID
GET /v1/meta/overview Discovery: scope×kind, progetti, agenti, superseduti (cache 60s)
GET /v1/status Health + statistiche

Auth: header X-API-Key (chiave condivisa, accesso completo). Rate limit 120 req/min per chiave. Audit log in JSON lines (docker logs).

Versione del codice

GET /v1/version (pubblico) espone la versione del codice in esecuzione, inclusa l'hash del commit Git da cui è stato costruito il container:

{"version": "2.7.0", "git_commit": "eccb2cb...", "guardrail_version": "similarity-v1", ...}

Anche GET /v1/status include version, git_commit e guardrail_version. L'hash è iniettato al build via ARG GIT_COMMIT/ENV GIT_COMMIT nel Dockerfile (default unknown). Per costruire con l'hash:

docker compose build --build-arg GIT_COMMIT=$(git rev-parse HEAD) gateway
# o nel compose: build: { context: ./gateway, args: { GIT_COMMIT: ${GIT_COMMIT:-unknown} } }

Guardrail di similarità (v1)

Enforcement deterministico FUORI dall'LLM, prima di ogni scrittura su POST /v1/memories:

  1. Strato 1 — hash esatto: SHA-256 del testo normalizzato (text_hash nel payload). Se esiste un record attivo con lo stesso hash → 409 BLOCK (EXACT_DUPLICATE).
  2. Strato 2 — similarità semantica top-3: embedding BGE-M3 cosine sui record attivi (esclusi i superseded).
    • top-1 ≥ GUARDRAIL_BLOCK_THRESHOLD (default 0.85) → 409 BLOCK (KNOWN_SOLUTION)
    • top-1 ≥ GUARDRAIL_WARN_THRESHOLD (default 0.70) → WARN: salva con flag guardrail nel payload
    • altrimenti → ALLOW

Il supersede esplicito (supersedes_id) è una correzione intenzionale: bypassa il guardrail.

Configurazione (env): GUARDRAIL_ENABLED (default true), GUARDRAIL_BLOCK_THRESHOLD, GUARDRAIL_WARN_THRESHOLD. Soglie di partenza da calibrare sul corpus reale.

Risposta BLOCK (409):

{"detail": {"error": "duplicate_memory", "reason": "KNOWN_SOLUTION", "matches": [{"memory_id": "...", "score": 0.92}], "message": "..."}}

Sicurezza

  • Qdrant bindato su 127.0.0.1; gateway solo su interfaccia VPN
  • Chiavi in .env (0600), mai committate
  • JWT RBAC su Qdrant (admin + read-only)
  • Backup: snapshot Qdrant + rotazione 7 giorni (cron: 0 3 * * * /opt/memory/backup.sh)

Dettagli operativi

Procedure complete (teardown, restore, nginx, troubleshooting): vedi docs/playbook.md nel repo pi-qmem.