ncm_semantic_triggers
NCM Semantic Trigger Matcher — cosine-similarity-based emotion detection.
Replaces the exact-word scan_text_for_triggers with embedding-based
semantic matching. Each emotion in reality_marble_recursion_index.yaml
gets:
An embedding of its affect description string.
LLM-generated colloquial phrases a person might say when feeling that emotion, each also embedded.
A
mean_vec(L2-normalized centroid of all above embeddings) that serves as the emotion’s semantic fingerprint for matching.
At runtime, the incoming text is embedded once and dot-producted against
every cached mean_vec. Emotions above MATCH_THRESHOLD are returned
as (emotion_name, delta_vector) pairs, capped at TOP_N.
Falls back to an empty list (caller should use scan_text_for_triggers
from ncm_delta_parser) when no embeddings are ready yet.
Redis key: ncm:trigger_embed:{sha256_hex_of_emotion_name} Redis value: JSON object — see below
- class ncm_semantic_triggers.SemanticTriggerMatcher(redis_client=None, api_key=None, openrouter_client=None)[source]
Bases:
objectCosine-similarity emotion trigger detector.
- Parameters:
redis_client – An
redis.asyncio.Redisinstance. May be None.api_key (
Optional[str]) – OpenRouter API key. When None the matcher is a no-op andfind_triggersalways returns an empty list.openrouter_client (OpenRouterClient | None)
- __init__(redis_client=None, api_key=None, openrouter_client=None)[source]
Initialize the instance.
- Parameters:
redis_client – Redis connection client.
openrouter_client (
OpenRouterClient|None) – Shared OpenRouterClient for connection pooling and batch embedding. Falls back to direct HTTP when None.
- Return type:
None
- async find_triggers(text, threshold=0.55, top_n=6)[source]
Embed text and return top-N emotions above threshold.
Returns list of (emotion_name, delta_vector) tuples, sorted by descending similarity. Returns an empty list if no embeddings are ready (caller should fall back to exact matching).
- async ensure_all_cached()[source]
Build the full emotion embedding index.
- Return type:
- For each emotion in the recursion index:
Load from Redis if already cached.
Otherwise embed the affect string + generate/embed 5 variant trigger phrases, then store in Redis.
Designed to run once at startup as a background task. Safe to call multiple times — already-cached emotions are skipped.