Skip to content

Core API (semvec)

The semantic-state engine. All symbols listed here are importable directly from semvec.

SemvecState

The persistent semantic state.

from semvec import SemvecState, SemvecConfig

state = SemvecState(config=SemvecConfig(dimension=384))

Constructor

Parameter Type Default Description
config SemvecConfig \| None SemvecConfig() Configuration bundle (see below).
license_key str \| None None License JWT passed programmatically (0.7.3+). Takes precedence over the SEMVEC_LICENSE_KEY environment variable — useful when the key comes from a .env file or a secret store and is never exported to the process environment. An invalid or empty key falls back to Community tier.

tier (read-only property)

The active license tier resolved at construction: "community", "pro", or "enterprise" (0.7.3+). Community is rate-limited per state (5 QPS / 50 burst); Pro and Enterprise lift or remove the limiter — see Licensing.

state = SemvecState(SemvecConfig(dimension=384), license_key=my_jwt)
assert state.tier == "enterprise"

update(input_embedding, text, *, meta=None, dedup_threshold=None, include_mutations=False) -> dict

Fold a single (embedding, text) pair into the state. meta is an optional dict attached to the resulting memory entry; dedup_threshold is a per-call cosine override for the attached dedup_signal (storage stays append-only). include_mutations adds a mutations list to the return — see below.

Returns a metric dict:

Key Type Meaning
similarity float Cosine similarity between input and current state, pre-update.
beta float Adaptive blending coefficient for this turn.
pattern_strength float How strongly retrieved memories pulled the state.
fsm float Stability score in [0, 1] (high = converged, low = oscillating).
phase str Detected phase (initialization / exploration / convergence / resonance / stability / instability).
norm float L2 norm of the post-update state vector.
topic_switch float Signalled topic-switch magnitude (0 = none).
novelty_score float How semantically novel this input was.
dedup_signal dict {is_update, max_sim, matched_id} — see preview_dedup below.
mutations list[dict] Only when include_mutations=True. What this turn changed in memory.

include_mutations=True — what the turn changed

Evictions happen silently. Without this flag the only way to notice that a memory is gone is to look for it and not find it, which is why callers ended up diffing whole snapshots between turns.

result = state.update(embedding, text, include_mutations=True)
for change in result["mutations"]:
    print(change)
# {'kind': 'added',   'id': '019fbcf3-a4a0-7611-bc3e-b2ca98f5f5d6'}
# {'kind': 'evicted', 'id': '019fbcf3-a4a4-7f52-ad54-295c7609ad5b'}

Each entry has kind and id; a merged entry additionally carries sources, the ids it replaced.

kind Meaning
added the unit was taken in
promoted / demoted it changed tier — existence is unchanged
evicted it is gone from every tier; terminal
merged a new unit replaces those named in sources

The tier distinction matters more than it looks. A unit is held by several tiers at once, so leaving one is not a removal — an earlier release reported those as evicted and a downstream persistence mirror deleted rows that still existed.

Replaying the feed reconstructs live memory, which is what a mirror needs.

Which kinds you actually see depends on the tier capacities, so handle all of them rather than the ones your test happened to produce. Measured with identical drivers:

Capacities Emitted Not emitted
2/2/2 added, promoted, demoted, evicted merged
3/3/3 added, promoted, demoted, merged evicted

At 3 the 80%-consolidation trigger fires and merging consumes units that would otherwise have been removed outright; at 2 it does not. A mirror that treats merged as optional loses the mapping from the replaced ids to their survivor; one that treats evicted as optional never removes anything.

Off by default for two reasons: it allocates on a hot path, and adding a key to the return unconditionally would change the shape every existing caller sees. The buffer is cleared on every turn whether or not you ask for it, so nothing accumulates when the flag stays off.

preview_dedup(input_embedding, *, dedup_threshold=None) -> dict

Read-only companion to update(). Computes the same dedup signal update() would attach as dedup_signal, but without storing the candidate or mutating any state — useful when a RAG / agent frontend needs to decide whether to commit to the actual update() call.

Returns the dedup-signal dict directly (no wrapping key):

Key Type Meaning
is_update bool max_sim > threshold.
max_sim float Cosine similarity to the closest prior memory. 0.0 on cold start.
matched_id str \| None UUIDv7 of the memory that produced max_sim, or None when no match.

Threshold lookup mirrors update(): the per-call dedup_threshold= argument wins, otherwise SemvecConfig.dedup_update_threshold (default 0.85) is used.

preview_dedup() does not consume the per-state rate-limit bucket — it is safe to poll at high frequency.

sig = state.preview_dedup(embedding)
if not sig["is_update"]:
    state.update(embedding, text)

Other methods

Method Purpose
add_anchor(embedding) Register a drift anchor — biases retrieval toward the anchor's domain.
add_resonance_trigger(trigger) Register a pre-built ResonanceTrigger(keyword=..., embedding=..., threshold=0.7, weight=1.0). Boosts memories on keyword or embedding match during retrieval.
add_resonance_trigger(trigger) Low-level: register a pre-built ResonanceTrigger instance (e.g. one you've round-tripped through a snapshot or constructed manually).
to_dict(*, include_memory_text=True, include_literal_cache_text=True, include_adaptive_params=True) -> dict Checksummed, JSON-safe full-state snapshot. The three keyword-only privacy toggles are independent; see "Snapshot redaction" below.
from_dict(data) -> SemvecState Restore from a to_dict() snapshot. Raises StateCorruptionError on checksum mismatch. Tolerates pre-redaction snapshots that lack the optional sections.
to_bytes(compress=True, *, include_memory_text=True, include_literal_cache_text=True, include_adaptive_params=True) -> bytes Compact binary checkpoint with magic header + corruption check. Same redaction kwargs as to_dict(). compress=False skips gzip for hot-path persistence. (provided by the Rust core; not surfaced in Python type stubs)
from_bytes(blob) -> SemvecState Restore from a to_bytes() blob (auto-detects compressed vs uncompressed via the version byte). (provided by the Rust core; not surfaced in Python type stubs)
set_retrieval_projection_weights(matrix) Inject a custom retrieval projection matrix (advanced; pins retrieval scoring across replays).
get_retrieval_projection_weights() -> list[list[float]] Snapshot the current projection matrix. Useful for parity tests; treat the contents as opaque.

Snapshot redaction

to_dict / to_bytes carry three independent privacy toggles for sharing snapshots outside trusted hands. All three default to True (back-compat) and can be combined freely:

Toggle Default When False, redacts
include_memory_text True The user-prose text on every memory entry — embedding, hash, scores stay so retrieval against the snapshot remains functional.
include_literal_cache_text True The verbatim text inside LiteralCache extracted facts (Decisions / Errors / Code structures). The structured fields and hashes stay.
include_adaptive_params True The adaptive_params block and the internal config block (field names intentionally undocumented). Strip when sharing snapshots outside trusted hands.

from_dict / from_bytes accept redacted snapshots — missing fields fall back to SemvecConfig defaults, and the integrity checksum is computed against those same defaults so the verification still succeeds.

The checksum is an integrity check, not a state identity

to_dict()["checksum"] answers one question: was this snapshot altered between writing and reading? It is computed over the state as this version represents it, and it is not comparable across semvec versions.

Two versions can produce different checksums for what looks like the same conversation without the algorithm changing at all, because a fix that changes the state changes the hash. A real example: 0.8.5 stopped discarding the cluster membership of units that were still alive, so the same input yields four clusters where 0.8.4 yielded three — different state, therefore a different checksum, same algorithm.

So do not use it to decide whether two versions agree about a conversation, and do not read a changed value as evidence that the hashing changed. If you need to detect drift across an upgrade, compare the fields you care about from to_dict(). Within one version the checksum is exact and stable: the same state hashes the same way every time.

Restore fidelity of calculate_fsm / calculate_metrics is licence-gated

A restore reproduces memories, retrieval and the update trajectory on every tier. The absolute values of the three calculate_* diagnostics below are reproduced only on an official wheel, with a Pro or Enterprise licence, and under the same licence subject that wrote the snapshot; otherwise they resume from a fresh salt and show a step change at the restore boundary. See What a restore reproduces.

# A snapshot you can hand to a third-party support engineer:
blob = state.to_bytes(
    include_memory_text=False,           # no user prose
    include_literal_cache_text=False,    # no verbatim facts
    include_adaptive_params=False,       # no internal tuning state
)

Aggregate diagnostics methods

SemvecState exposes a small set of on-demand diagnostics methods for dashboards and ops monitoring beyond what update() returns. Treat their return values as opaque indicators — useful for UI / monitoring / dispatch logic in your application, but not as a window into engine mechanics.

Method Returns Purpose
calculate_fsm(...) float in [0, 1] Overall stability score (higher = more stable). Useful for gating expensive actions on > 0.7.
calculate_metrics(...) dict[str, float] Internal diagnostics dict for ops dashboards.
calculate_advanced_metrics(...) dict[str, float] Extended diagnostics dict (super-set of calculate_metrics).

Keys and argument signatures are unstable

The exact keys in the diagnostics dicts, their interpretation, and the argument signatures of these methods are implementation details and may change between releases without notice.

Iterate the returned dict defensively (for k, v in d.items()) instead of hard-coding key names so your code stays forward-compatible.

The values are deterministic for a given (subject, dimension, input) tuple within a release; do not assume cross-release or cross-instance comparability. Outputs are licensing-bound — see licensing.

Attributes

Attribute Type Notes
semantic_state np.ndarray The live state vector, shape (dim,). Readable and writable.
interaction_count int Total update() calls since construction or reset. (runtime attribute, not in stub)
timestamp int Monotonic tick counter. (runtime attribute, not in stub)
memory MultiResolutionMemory Short-term / medium-term / long-term tiers. (runtime attribute, not in stub)
phase_detector PhaseDetector Automatic phase detector. (runtime attribute, not in stub)
literal_cache LiteralCache Verbatim structured-memory layer. (runtime attribute, not in stub)
anchor_count int Number of registered drift anchors. (runtime attribute, not in stub)
anchor_score float Mean cosine of state vs all registered anchors. (runtime attribute, not in stub)
topic_switch_history list[dict] Bounded list of detected switches. (runtime attribute, not in stub)
phase_history list[str] Phase transitions recorded since construction.

Additional methods

Further public methods on SemvecState, surfaced here for completeness. Argument lists reflect the installed wheel; treat return values as opaque indicators (see the diagnostics warning above).

Method Purpose
inject_memory(embedding, text, tier, importance=1.0, timestamp=0.0, access_count=0, meta=None, protection_score=0.0) Manually seed a memory at a specific tier; useful for warmstarts and migration.
consolidate_long_term() Run a single consolidation pass over the long-term tier.
get_all_memories_flat() Flat list view of every memory across all tiers.
get_total_stored() Total number of memories currently held across all tiers.
get_metrics() Snapshot of the last computed metric dict.
get_phase() Current phase label.
get_dynamic_top_k() Suggested retrieval top-k for the current state.
query_similarities_vectorized(query_embedding) Batch similarity scoring against the live state.
add_negative_attractor(error_vector, description=..., source=..., severity=1.0) Register a negative attractor to demote in retrieval.
clear_negative_attractors() Remove all registered negative attractors.
clear_resonance_triggers() Remove all registered resonance triggers.
set_isolation_filter(filter_) Restrict retrieval to memories matching the supplied filter.
release_quarantine_count() Number of memories released from quarantine since construction.
update_batch(...) Batched variant of update() for bulk ingestion.

Diagnostic attributes

Rolling-history and counter attributes exposed for dashboards and ops monitoring. Treat their contents as opaque indicators — useful for UI / monitoring in your application, not as a window into engine mechanics. Lengths are bounded by SemvecConfig.history_length.

Attribute Type Notes
similarity_history list[float] Rolling history of per-turn similarity values.
norm_history list[float] Rolling history of post-update state-vector norms.
beta_history list[float] Rolling history of adaptive blending coefficients.
fsm_history list[float] Rolling history of stability scores.
drift_threshold float Current drift threshold used by the detector.
negative_attractor_count int Number of currently registered negative attractors.
resonance_trigger_count int Number of currently registered resonance triggers.
realignment_remaining int Remaining steps in any active realignment.
operator_state_vector np.ndarray Companion vector tracking operator-side state.
config SemvecConfig The config object the state was constructed with.

SemvecConfig

Immutable configuration dataclass passed into SemvecState(config=…). Every field is a keyword argument; everything has a default so SemvecConfig() is a valid call.

from semvec import SemvecConfig

cfg = SemvecConfig(dimension=384)

Fields

Every SemvecConfig field is a keyword argument; everything has a default so SemvecConfig() is a valid call. Out-of-range values raise ConfigurationError in the constructor.

Field descriptions describe what each knob is for, not the underlying mechanism. The mechanism is out of scope for this reference.

Identity & embedder

Field Type Default Purpose
model_name str "all-MiniLM-L6-v2" Preferred embedder label (informational hint — the state never loads a model itself).
dimension int 384 Embedding dimension. Must match your embedder's get_dimension().
device str "cpu" Device hint for the embedder (informational).
debug bool False Enable verbose core logging.

Memory tiers & retention

Field Type Default Purpose
short_term_size int 15 Short-term memory capacity.
medium_term_size int 50 Medium-term memory capacity.
long_term_size int 200 Long-term memory capacity.
use_selective_forgetting bool True Score-based eviction when a tier overflows vs FIFO.
compression_ratio float 0.3 Text-compression ratio on promotion between tiers. Lower = shorter compressed output per turn, less retained nuance. Tune in [0.1, 0.5].

Phase detector & rolling windows

Field Type Default Purpose
phase_detection_window int 50 Sliding-window size the phase detector consumes.
context_window int 20 Recent-input window kept for novelty / topic-switch scoring.
history_length int 20 Cap on rolling history arrays (norm_history, similarity_history, beta_history).

Topic-switch detector

Field Type Default Purpose
enable_topic_switch bool True Master switch for the topic-switch detector.
topic_switch_threshold float 0.3 Sensitivity knob — raise to make the detector less twitchy on noisy domains, lower to make it fire sooner.
topic_switch_window int 5 Number of consecutive turns the detector watches.
auto_anchor_on_topic_switch bool False When True, snapshot the current semantic_state as a fresh anchor on every detected switch.
max_auto_anchors int 8 Cap on anchors created via auto_anchor_on_topic_switch.

Retrieval boosts & tier weights

Field Type Default Purpose
anchor_retrieval_boost float 0.6 Score boost applied when registered anchors align with the candidate. Tune in [0.1, 0.6].
trigger_retrieval_boost float 0.3 Score boost applied when a ResonanceTrigger matches. Tune in [0.1, 0.6].
short_term_weight float 1.0 Tier weight for short-term memories during retrieval.
medium_term_weight float 0.95 Tier weight for medium-term memories.
long_term_weight float 0.9 Tier weight for long-term memories.
negative_attractor_penalty float 0.5 Overall strength of NegativeAttractor demotion in retrieval ([0, 1]). (advanced; rarely changed — internal stability safeguard, leave at default unless a benchmark instructs otherwise)
negative_attractor_threshold float 0.3 Cosine floor below which attractors are ignored.
cluster_fallback_threshold float 0.85 Controls retrieval breadth for uncertain matches against the long-term tier. Higher values keep older domains reachable; lower values stay narrow.

Internal tuning constants

Four internal tuning constants plus the adaptive_params block are stripped from snapshots when you pass include_adaptive_params=False to to_dict() / to_bytes(); their names are intentionally not documented — see llms.txt for the disclosure policy.

MultiResolutionMemory

Three-tier episodic memory. Exposed via state.memory.

Method Returns Purpose
get_relevant_memories(query_embedding, top_k=10, *, meta_filter=None) list[MemoryUnit] Cosine-similarity retrieval across all tiers. Optional meta_filter dict restricts results to memories whose meta matches.
short_term / medium_term / long_term list[MemoryUnit] Direct tier access.

MemoryUnit

Attribute Type
embedding np.ndarray
text str
importance float
access_count int
timestamp float
semantic_hash str (8-hex-char content hash)
protection_score float (retention bias for selective forgetting)

PhaseDetector

Exposed via state.phase_detector.

  • current_phase: str
  • phase_transitions: list[dict] — historical transitions with timestamps and metric snapshots.
  • update(metrics, timestamp) -> Optional[str] — returns the new phase if a transition occurred.
  • signal_topic_switch(magnitude) — bias the next rule-scoring pass toward exploration.

LiteralCache

Exact-text structured-memory layer. See Coding API for the full surface — recording, querying (query(text, max_results=10)), and build_handoff_context() for cross-session prompts.

safe_cosine_similarity(a, b, eps=1e-8) -> float

Cosine similarity that returns 0.0 on zero-norm vectors instead of NaN.

Exceptions

from semvec import (
    SemvecError,                # base class
    ConfigurationError,
    EmbeddingError,
    StateCorruptionError,
    LicenseError,            # base for licensing issues
    LicenseExpiredError,
    RateLimitError,
)

All inherit from SemvecError. License-related exceptions inherit from LicenseError → SemvecError.

RateLimitError exceptions carry the standard Python args tuple; parse for retry hints if needed. (A dedicated retry_after attribute is planned for a future release.)

See also