Memory System Data Models
Last Updated: 2026-02-06
Content-Type: Reference
Audience: Developers
Database Schema
Memories Table
Table: memories
| Field | Type | Description |
|---|---|---|
id | INTEGER | Primary key |
userId | INTEGER | User who owns this memory (NULL = world/global) |
content | TEXT | Memory content |
source | STRING | Memory source tag (e.g. conversation, diary, world-lore-v1) |
embedding | VECTOR | Embedding vector (pgvector vector(VECTOR_DIM)) |
conversation_id | INTEGER | Conversation/thread ID (optional) |
file_source | STRING | File import/source identifier (optional) |
createdAt | TIMESTAMP | Creation timestamp |
Notes:
- This codebase does not maintain
updatedAtformemories(it is effectively append-only).
Memory Chunks Table
Table: memory_chunks
Chunk rows power chunked hybrid retrieval.
| Field | Type | Description |
|---|---|---|
id | INTEGER | Primary key |
memoryId | INTEGER | Parent memory ID (memories.id) |
userId | INTEGER | Owner user (NULL = world/global) |
conversationId | INTEGER | Conversation/thread ID (optional, continuity boost) |
tier | STRING | world | aso | personal |
source | STRING | Source tag copied from memory (optional) |
chunkIndex | INTEGER | Chunk order within a memory |
content | TEXT | Chunk text |
embedding | VECTOR | Chunk embedding (vector(VECTOR_DIM)) |
createdAt | TIMESTAMP | Created timestamp |
updatedAt | TIMESTAMP | Updated timestamp |
RAG Traces Table (Optional)
Table: rag_traces
Persisted only when RAG_TRACE=true to help debugging retrieval quality.
| Field | Type | Description |
|---|---|---|
id | INTEGER | Primary key |
userId | INTEGER | Target user |
conversationId | INTEGER | Conversation/thread (optional) |
queryText | TEXT | Query that triggered retrieval |
chunks | JSONB | Retrieved chunks (tier/score/content) |
meta | JSONB | Debug metadata (path, depth, etc.) |
createdAt | TIMESTAMP | Created timestamp |
TypeScript Interfaces
Memory Model
typescript
interface Memory {
id: number;
userId: number;
content: string;
source: 'world' | 'aso_core' | 'shared' | 'image_ocr_extraction' | 'document_ingestion' | 'vision_analysis';
embedding?: number[];
metadata?: MemoryMetadata;
conversationId?: number;
createdAt: Date;
updatedAt: Date;
}Memory Metadata
typescript
interface MemoryMetadata {
conversationId?: number;
fileContext?: string;
visionContext?: string;
uploadContextId?: string;
playerName?: string;
npcName?: string;
yexianInstanceId?: number;
personaId?: number;
}Memory Data (for creation)
typescript
interface MemoryData {
userId: number;
content: string;
source: 'world' | 'aso_core' | 'shared';
metadata?: MemoryMetadata;
conversationId?: number;
}Full Context
typescript
interface FullContext {
memories: Memory[];
persona: Persona;
emotions: Emotions;
quests: Quest[];
inventory: InventoryItem[];
}Embedding Configuration
Embedding Provider (Configurable)
Embeddings are generated by backend/src/services/embedding.service.ts.
- Gemini:
gemini-embedding-001 - OneAPI/OpenAI-compatible:
POST /v1/embeddingsviaONE_API_URL+ONE_API_KEY
Key env vars:
EMBEDDING_PROVIDER=gemini|oneapiONE_API_EMBEDDING_MODEL=text-embedding-3-small(1536 dims) or another allowed modelVECTOR_DIM=1536(must match the DB vector column dimension)EMBEDDING_CACHE_SIZE=500(optional)
Vector Similarity Search SQL
sql
SELECT
id,
content,
source,
embedding <-> CAST(:queryVector AS vector) AS distance
FROM "memories"
WHERE "userId" = :userId AND embedding IS NOT NULL
ORDER BY distance
LIMIT :limit;Memory Source Types
| Source | Description | Scope |
|---|---|---|
world | Universal knowledge, game world rules | All users |
aso_core | Core identity and beliefs | All users (immutable) |
shared | User-specific conversations | Per user |
image_ocr_extraction | OCR text from images | Per user |
document_ingestion | Processed documents | Per user |
vision_analysis | Image vision analysis | Per user |
Related Documentation
- API Reference - Function signatures and usage
- Architecture - System design details