Mem0 Memory Engine¶
The Mem0 memory engine powers long-term character memory in OpenTalking. It stores durable user preferences, stable facts, and multi-turn summaries, then recalls relevant memories before the next LLM call. This is separate from the knowledge-base/RAG flow: knowledge bases are for uploaded documents, while memory libraries are for long-lived user-character interaction state.
Current implementation
OpenTalking currently integrates Mem0 through the open-source mem0.Memory SDK and keeps its own /memory/* APIs, memory libraries, items, and scope model. Switching the provider to Mem0 does not remove the existing list/import/delete memory API surface.
Where Mem0 Fits¶
flowchart TD
User["User input"] --> Runtime["MemoryRuntime"]
Runtime --> Decision["MemoryDecisionAgent<br/>recall/write decision"]
Decision --> Recall{"Recall?"}
Recall -->|yes| Search["Mem0 search<br/>or hybrid fallback"]
Search --> Prompt["Memory snippets injected into LLM prompt"]
Decision --> Write{"Write?"}
Write -->|smart write| AddInfer["Mem0 add(messages, infer=true)"]
Write -->|raw write| AddRaw["Mem0 add(text, infer=false)"]
Runtime --> Summary{"Summary enabled?"}
Summary -->|window reached| Summarize["OpenTalking LLM creates summary"]
Summarize --> AddSummary["Mem0 add(summary, infer=false)"]
OpenTalking still owns:
- Scope:
profile_id + character_id + library_id. - Memory APIs: create libraries, list items, import turns, delete items.
- Recall decisions: low-value inputs are skipped.
- Multi-turn summary generation: OpenTalking uses the configured main LLM, then writes the summary through the provider.
Mem0 provides:
- Memory storage and semantic search.
- Smart extraction from conversation messages when
smart_write_enabled=trueand the installed SDK supportsinfer. - Mem0-side semantic recall, deduplication, and disambiguation behavior. OpenTalking does not expose a separate manual disambiguation endpoint.
Dependencies¶
The current 146 environment uses the compatible set below:
protobuf is pinned to 4.x to avoid conflicts between newer mem0ai releases and the existing mediapipe dependency. Re-run python -m pip check and the memory tests before upgrading the Mem0 SDK.
.env Configuration¶
OpenTalking defaults to the Mem0 smart memory engine and smart orchestration, but conversation memory still runs only when the session/persona enables memory_enabled: if memory is not enabled for that conversation, OpenTalking does not recall or write memories. When memory is enabled and no explicit library is provided, OpenTalking uses its internal default memory library.
Most deployments only need the summary settings and the models Mem0 uses internally:
OPENTALKING_MEMORY_SUMMARY_ENABLED=true
OPENTALKING_MEMORY_SUMMARY_TURN_WINDOW=8
OPENTALKING_MEMORY_SUMMARY_MAX_ITEMS=3
OPENTALKING_MEMORY_MEM0_LLM_PROVIDER=openai
OPENTALKING_MEMORY_MEM0_LLM_BASE_URL=https://dashscope.aliyuncs.com/compatible-mode/v1
OPENTALKING_MEMORY_MEM0_LLM_API_KEY=<llm-api-key>
OPENTALKING_MEMORY_MEM0_LLM_MODEL=qwen-flash
OPENTALKING_MEMORY_MEM0_EMBEDDER_PROVIDER=openai
OPENTALKING_MEMORY_MEM0_EMBEDDER_BASE_URL=https://dashscope.aliyuncs.com/compatible-mode/v1
OPENTALKING_MEMORY_MEM0_EMBEDDER_API_KEY=<embedding-api-key>
OPENTALKING_MEMORY_MEM0_EMBEDDER_MODEL=text-embedding-v4
Internal defaults already select the Mem0 provider, hybrid recall/write, rules-first plus Mem0/LLM second-stage judgement, and smart writes. OPENTALKING_MEMORY_MEM0_CONFIG is still supported as an advanced compatibility override: when it is set, OpenTalking passes that JSON to Mem0 instead of building config from the split variables above.
LLM, Embedding, And Vector Store¶
| Config | Purpose |
|---|---|
llm |
Model Mem0 uses to understand conversations and extract or rewrite durable memories. |
embedder |
Model that converts memory text into vectors for semantic retrieval. |
vector_store |
Storage backend for vectors, metadata, and indexes, such as Qdrant, Chroma, or pgvector. It is not the OpenTalking memory-library UI; it is Mem0's retrieval database. |
OpenTalking's main LLM is still configured with OPENTALKING_LLM_*. The llm/embedder/vector_store block only affects Mem0's own memory extraction and retrieval.
Recall Decision Mode¶
OPENTALKING_MEMORY_DECISION_MODE controls the pre-recall decision:
| Value | Behavior |
|---|---|
rule |
Default. Uses local rules only, with the lowest latency. |
hybrid |
Rules run first. Empty inputs, low-value inputs, and high-risk operations are hard rejects; clear user-memory, fact-entity, and explicit-recall matches recall directly; only ambiguous inputs call the LLM judge. |
llm |
Experimental. Hard rejects remain rule-protected; other inputs are judged by the LLM. |
OPENTALKING_MEMORY_DECISION_TIMEOUT_MS is the second-stage judge timeout. If the LLM judge times out or fails, OpenTalking falls back to the rule result and continues the conversation.
Is MEM0_API_KEY Required?¶
For the current OpenTalking adapter, no. It uses the open-source mem0.Memory class, not MemoryClient, so MEM0_API_KEY is not required. You only need the LLM, embedding, and vector-store configuration used by the open-source Mem0 runtime; those services may have their own API keys or local endpoints.
MEM0_API_KEY is required only if the project later switches to Mem0 Platform / MemoryClient. Platform pricing depends on Mem0's current plans and is not required for this adapter.
Impact On Existing Memory APIs¶
With OPENTALKING_MEMORY_PROVIDER=mem0, the OpenTalking memory API remains the same:
curl "http://127.0.0.1:8000/memory/libraries?profile_id=default&character_id=<avatar-id>"
curl "http://127.0.0.1:8000/memory/libraries/default/items?profile_id=default&character_id=<avatar-id>"
Notes:
- Item listing uses Mem0
get_all(...), then OpenTalking filters byprofile_id,character_id, andlibrary_id. - OpenTalking stores the raw Mem0 id as
_mem0_idand keeps its ownopentalking_memory_idfor stable API-facing ids. - Item deletion uses
_mem0_idwhen calling Mem0 delete. memory_recall_backend=hybridfalls back to local BM25 item ranking when Mem0 returns no result;memory_recall_backend=mem0uses Mem0 only.
Verification¶
Check provider initialization:
python - <<'PY'
from opentalking.core.config import get_settings
from opentalking.providers.memory.factory import build_memory_provider
get_settings.cache_clear()
provider = build_memory_provider()
print(type(provider).__name__)
PY
Import and list one memory:
curl -s -X POST http://127.0.0.1:8000/memory/libraries \
-H 'content-type: application/json' \
-d '{"id":"default","name":"Default","character_id":"demo-avatar"}'
curl -s -X POST http://127.0.0.1:8000/memory/libraries/default/import \
-H 'content-type: application/json' \
-d '{"profile_id":"default","character_id":"demo-avatar","turns":[{"role":"user","content":"Remember that I prefer concise answers."}]}'
curl -s "http://127.0.0.1:8000/memory/libraries/default/items?profile_id=default&character_id=demo-avatar"
After changing SDK versions or dependencies, run:
python -m pip check
python -m pytest tests/unit/test_memory_provider.py apps/api/tests/test_memory_api.py apps/api/tests/test_config.py