symfonic.memory.layers.episodic_events¶
episodic_events ¶
The episodic layer's event API: store, list, count, query.
Split out of :mod:symfonic.memory.layers.episodic (320 lines against the
300-line budget). What stayed behind is the BaseMemoryStore contract -- the
five uniform methods every layer implements, plus prompt rendering. What moved
here is the layer-specific domain API the file itself already separated under a
Layer-specific domain methods heading: the four calls that speak in events
and timestamps rather than in entries.
EpisodicLayer mixes this in, so every method is reached exactly as before.
EpisodicEventsMixin ¶
Event storage and time-ordered reads for :class:EpisodicLayer.
The three attributes below are supplied by the host layer; they are declared here so the mixin's reads are typed rather than implicit.
count_events
async
¶
Return the total number of stored episodic events for the tenant.
Delegates to VectorBackend.count() when available, otherwise falls back to 0 to avoid a full scan with an arbitrary embedding.
Source code in src/symfonic/memory/layers/episodic_events.py
list_events
async
¶
Return up to limit episodic events for the tenant.
Uses a neutral zero-vector query so that all stored events are
returned in approximate descending-similarity order (deterministic
for vectors with the same embedding, arbitrary but consistent
otherwise). Prefer this over query_events when you need a
full listing rather than a relevance-ranked subset.
Parameters:
| Name | Type | Description | Default |
|---|---|---|---|
scope
|
TenantScope
|
Tenant scope for isolation. |
required |
limit
|
int
|
Maximum number of events to return (default 1000). |
1000
|
Returns:
| Type | Description |
|---|---|
list[MemoryEntry]
|
List of MemoryEntry instances (order: most-similar first). |
Notes
v7.13.6: when the embedder rejects embed("") (the OpenAI
embeddings endpoint returns 400 "input cannot be an empty
string") we transparently fall back to embed(" "). The
single-space probe is non-empty for OpenAI's validator while
remaining distance-agnostic enough to enumerate stored events
via similarity ranking. Sentence-transformers and other
backends that accept empty strings continue to use the
zero-string path. Fixes the v7.13.4 quick_nap phase-10 WARN
reported by adopter.
Source code in src/symfonic/memory/layers/episodic_events.py
query_events
async
¶
Query episodic events by vector similarity.
Parameters:
| Name | Type | Description | Default |
|---|---|---|---|
scope
|
TenantScope
|
Tenant scope for isolation. |
required |
query
|
str
|
Natural language query to search against. Must be a non-empty, non-whitespace string. |
required |
top_k
|
int
|
Maximum number of results to return. |
5
|
Returns:
| Type | Description |
|---|---|
list[MemoryEntry]
|
List of MemoryEntry instances ranked by similarity. |
Raises:
| Type | Description |
|---|---|
ValueError
|
If |
Source code in src/symfonic/memory/layers/episodic_events.py
store_event
async
¶
store_event(scope: TenantScope, event: MemoryEntry, *, source_phase: str = 'episodic.store_event') -> None
Store an event with its embedding in the vector backend.
Parameters:
| Name | Type | Description | Default |
|---|---|---|---|
scope
|
TenantScope
|
Tenant scope for isolation. |
required |
event
|
MemoryEntry
|
The memory entry representing the event. |
required |
source_phase
|
str
|
Tag identifying which caller triggered the
write (e.g. |
'episodic.store_event'
|
v6.2 T05 telemetry: when the caller populates event.metadata
with any of tokens_in / tokens_out / input_tokens /
output_tokens / cost_usd / model /
embedding_latency_ms, the values are lifted onto the
:class:EpisodicTelemetryRecord for the corpus. Keys missing
from metadata remain None and are stripped from the JSONL
line (v6.1 shape preserved byte-for-byte). The engine can source
the token / cost fields from LLMPreCallEvent /
LLMEndEvent and attach them to the metadata before calling
store_event; direct callers that do not consume LangChain
callbacks may pass the values in metadata themselves.
Source code in src/symfonic/memory/layers/episodic_events.py
42 43 44 45 46 47 48 49 50 51 52 53 54 55 56 57 58 59 60 61 62 63 64 65 66 67 68 69 70 71 72 73 74 75 76 77 78 79 80 81 82 83 84 85 86 87 88 89 90 91 92 93 94 95 96 97 98 99 100 101 102 103 104 105 106 107 108 109 110 111 112 113 114 115 116 117 118 119 120 121 122 123 124 125 126 127 128 129 130 131 132 133 134 135 136 137 138 139 140 | |