AiPersona is an embeddable, on-device long-term memory engine for AI chat apps on Apple platforms — a bi-temporal knowledge graph, hybrid BM25 + embedding retrieval, and LLM-driven fact extraction and correction, reshaped from synapse-cortex's cognitive core for a single-user, embedded target instead of a multi-tenant server.
MemoryGraphStore holds EntityNode, EpisodicNode, and FactEdge SwiftData models. Corrections invalidate a fact by setting invalidAt — facts are never deleted, so the full history is always reconstructable.
upsertEntity tries an exact case-insensitive match first, then falls back to token-subset and initials matching. Embedding similarity is deliberately not used for names — word-vector embeddings have no real coverage for proper nouns.
invalidateFacts matches a correction to the fact it's actually about by cosine similarity, regardless of predicate string wording, and returns whether anything was actually invalidated — so a caller can tell the user when a correction didn't land.
IngestionActor is a Swift actor, so concurrent enqueue calls are naturally serialized — which also protects against extraction-provider rate limits with no extra concurrency-limiting code. Extraction failures are logged and swallowed; ingestion never surfaces as a user-facing error.
RetrievalService mirrors synapse-cortex's hydration + per-turn split: a cached, budgeted session compilation plus a per-turn BM25 + embedding hybrid search with reciprocal rank fusion.
Fact extraction and chat generation are independently selectable between on-device MLX, Gemini, OpenAI, and Anthropic — plus optional Notion export/import, knowledge-graph visualization export, and Gemini context caching.
.package(url: "https://github.com/NerdSnipe-Inc/AiPersona.git", from: "1.0.0").target(name: "YourApp", dependencies: ["AiPersona"])Depends on AIChatKit (AIChatCore, AIChatOpenAI, AIChatAnthropic) and AIChatKitMLX (AIChatMLX). Resolves from a sibling checkout if present, otherwise from GitHub — set SPI_PROCESSING or FORCE_REMOTE_PACKAGES to force remote resolution.
AiPersona stores and retrieves memory; it doesn't run a chat loop. It builds prompt fragments for a host app's own chat system to consume — no backend, no account system, and no user data sent anywhere unless the host app opts into an external LLM/embedding provider.
It's single-user by design: one local user per host app instance, unlike the multi-tenant FastAPI server (synapse-cortex) it's adapted from.
No. AiPersona is fully on-device by default, using SwiftData for storage and Apple's NLEmbedding for local embeddings. A backend is only involved if you configure an external LLM/embedding provider for extraction.
AiPersona is a from-scratch Swift Package reimplementation of synapse-cortex's cognitive core, reshaped for a single-user, embedded target instead of a multi-tenant FastAPI server. See source-compared.md in the repo for a feature-by-feature comparison.
Yes — the graph exposes activeFacts(), allFacts() (including invalidated history), and allEntities(), so a host app can build a browse/correct/delete UI on top of it.
Add AiPersona alongside AIChatKit to give your chat app a local, bi-temporal memory graph — no backend required.