Compare commits
5 Commits
| Author | SHA1 | Date | |
|---|---|---|---|
| d5f9089361 | |||
| 55a4bcd26d | |||
| c0b1cd2666 | |||
| 809bccfbe7 | |||
| 49df324d99 |
@@ -39,7 +39,7 @@ This is a polyglot monorepo and **every package sets its own rules**. Read the `
|
||||
|
||||
| Directory | What it is |
|
||||
|-----------|------------|
|
||||
| `mem0/` | Core Python SDK (`mem0ai` on PyPI): memory, LLMs, embeddings, vector stores, graphs, rerankers |
|
||||
| `mem0/` | Core Python SDK (`mem0ai` on PyPI): memory, LLMs, embeddings, vector stores, rerankers |
|
||||
| `mem0-ts/` | TypeScript SDK (`mem0ai` on npm): hosted client + OSS memory |
|
||||
| `cli/python/` | Python CLI (`mem0-cli` on PyPI), Typer-based, entry point `mem0` |
|
||||
| `cli/node/` | Node CLI (`@mem0/cli` on npm), Commander-based, entry point `mem0` |
|
||||
@@ -59,8 +59,7 @@ mem0 (Python SDK) mem0-ts (TypeScript SDK)
|
||||
├── mem0/llms/ └── src/oss/ Memory (self-hosted)
|
||||
├── mem0/embeddings/ ├── src/llms/
|
||||
├── mem0/vector_stores/ ├── src/embeddings/
|
||||
├── mem0/graphs/ ├── src/vector_stores/
|
||||
└── mem0/reranker/ └── src/graphs/
|
||||
└── mem0/reranker/ └── src/vector_stores/
|
||||
|
||||
cli/python/ ──▶ mem0ai (optional, OSS mode)
|
||||
cli/node/ ──▶ mem0ai (npm)
|
||||
|
||||
@@ -211,6 +211,13 @@ is created with the correct tag prefix.
|
||||
| `@mem0/cli` (Node CLI) | npm | `cli-node-v*` | `cli-node-v0.1.2` |
|
||||
| `@mem0/vercel-ai-provider` | npm | `vercel-ai-v*` | `vercel-ai-v2.0.6` |
|
||||
| `@mem0/openclaw-mem0` | npm | `openclaw-v*` | `openclaw-v1.0.1` |
|
||||
| `@mem0/opencode-plugin` | npm | `opencode-v*` | `opencode-v1.0.1` |
|
||||
| `@mem0/pi-agent-plugin` | npm | `pi-agent-v*` | `pi-agent-v1.0.1` |
|
||||
| `@mem0/n8n-nodes-mem0` | npm | `n8n-nodes-mem0-v*` | `n8n-nodes-mem0-v1.0.1` |
|
||||
|
||||
The Zapier app (`integrations/zapier-mem0`) deploys to Zapier's own platform rather
|
||||
than a package registry, so it has no release tag. Deploy it manually with
|
||||
`gh workflow run zapier-mem0-cd.yml --ref main`.
|
||||
|
||||
### How to Release
|
||||
|
||||
|
||||
@@ -40,7 +40,7 @@ After installing, just ask Claude:
|
||||
- "Add memory to my chatbot"
|
||||
- "Help me search user memories with filters"
|
||||
- "Integrate mem0 with my LangChain app"
|
||||
- "Add graph memory to track entity relationships"
|
||||
- "Migrate my app from mem0 v2 to v3"
|
||||
|
||||
## What's Inside
|
||||
|
||||
@@ -56,7 +56,7 @@ skills/mem0/
|
||||
├── sdk-guide.md # All SDK methods (Python + TypeScript)
|
||||
├── api-reference.md # REST endpoints, filters, memory object
|
||||
├── architecture.md # Processing pipeline, lifecycle, scoping, performance
|
||||
├── features.md # Retrieval, graph, categories, MCP, webhooks, multimodal
|
||||
├── features.md # Retrieval, entity linking, categories, MCP, webhooks, multimodal
|
||||
├── integration-patterns.md # LangChain, CrewAI, Vercel AI, LangGraph, LlamaIndex, etc.
|
||||
└── use-cases.md # 7 real-world patterns with Python + TypeScript code
|
||||
```
|
||||
|
||||
@@ -36,9 +36,8 @@ SECTION_MAP = {
|
||||
"platform": [
|
||||
"/platform/overview",
|
||||
"/platform/quickstart",
|
||||
"/platform/features",
|
||||
"/platform/features/graph-memory",
|
||||
"/platform/features/selective-memory",
|
||||
"/platform/features/advanced-retrieval",
|
||||
"/platform/features/custom-categories",
|
||||
"/platform/features/v2-memory-filters",
|
||||
"/platform/features/async-client",
|
||||
@@ -57,10 +56,10 @@ SECTION_MAP = {
|
||||
"/open-source/overview",
|
||||
"/open-source/python-quickstart",
|
||||
"/open-source/node-quickstart",
|
||||
"/open-source/features",
|
||||
"/open-source/features/graph-memory",
|
||||
"/open-source/features/overview",
|
||||
"/open-source/features/rest-api",
|
||||
"/open-source/configure-components",
|
||||
"/open-source/features/metadata-filtering",
|
||||
"/open-source/configuration",
|
||||
],
|
||||
"sdks": [
|
||||
"/sdks/python",
|
||||
|
||||
+11
-11
@@ -1,6 +1,6 @@
|
||||
# Python SDK (`mem0/`)
|
||||
|
||||
The `mem0ai` package on PyPI. Memory core plus five pluggable provider categories.
|
||||
The `mem0ai` package on PyPI. Memory core plus four pluggable provider categories.
|
||||
|
||||
## Commands
|
||||
|
||||
@@ -35,10 +35,9 @@ mem0/
|
||||
├── memory/ Memory, AsyncMemory
|
||||
├── client/ MemoryClient, AsyncMemoryClient
|
||||
├── configs/ MemoryConfig and per-category config models
|
||||
├── llms/ 24 providers
|
||||
├── embeddings/ 15 providers
|
||||
├── vector_stores/ 30 providers
|
||||
├── graphs/ 4 providers
|
||||
├── llms/ 18 providers
|
||||
├── embeddings/ 11 providers
|
||||
├── vector_stores/ 25 providers
|
||||
└── reranker/ 5 providers
|
||||
```
|
||||
|
||||
@@ -48,10 +47,9 @@ Every category follows the same shape: a `base.py` with the abstract class, one
|
||||
|
||||
| Category | Count | Examples |
|
||||
|----------|-------|---------|
|
||||
| LLMs | 24 | OpenAI, Anthropic, AWS Bedrock, Azure OpenAI, Gemini, Groq, Ollama, Together, DeepSeek, vLLM, LiteLLM, LM Studio, xAI |
|
||||
| Vector stores | 30 | Qdrant, Pinecone, Chroma, Weaviate, Milvus, MongoDB, Redis, Elasticsearch, pgvector, Supabase, Faiss, S3 Vectors |
|
||||
| Embeddings | 15 | OpenAI, Azure OpenAI, Gemini, HuggingFace, FastEmbed, Together, AWS Bedrock, Ollama, Vertex AI |
|
||||
| Graph stores | 4 | Neo4j, Memgraph, Kuzu, Apache AGE |
|
||||
| LLMs | 18 | OpenAI, Anthropic, AWS Bedrock, Azure OpenAI, Gemini, Groq, Ollama, Together, DeepSeek, vLLM, LiteLLM, LM Studio, xAI |
|
||||
| Vector stores | 25 | Qdrant, Pinecone, Chroma, Weaviate, Milvus, MongoDB, Redis, Elasticsearch, pgvector, Supabase, Faiss, S3 Vectors |
|
||||
| Embeddings | 11 | OpenAI, Azure OpenAI, Gemini, HuggingFace, FastEmbed, Together, AWS Bedrock, Ollama, Vertex AI |
|
||||
| Rerankers | 5 | Cohere, HuggingFace, LLM-based, Sentence Transformer, Zero Entropy |
|
||||
|
||||
### Adding a provider
|
||||
@@ -100,6 +98,8 @@ Changing any of these signatures means updating `docs/` in the same PR.
|
||||
| Embedding provider | `from mem0.embeddings.<provider> import <ProviderEmbedding>` |
|
||||
| Vector store provider | `from mem0.vector_stores.<provider> import <ProviderVectorStore>` |
|
||||
|
||||
## Graph memory
|
||||
## Graph memory (Platform only)
|
||||
|
||||
An optional layer on top of vector memory for relationship-aware retrieval, configured through the `graph` section of `MemoryConfig`. It supplements vector search rather than replacing it.
|
||||
Removed from the OSS SDKs. `mem0/graphs/` and `mem0-ts/src/oss/src/graphs/` were deleted in `a488e1904` when the v3 pipeline landed; relationship-aware retrieval in OSS is now handled by entity extraction inside the pipeline itself. There is no `graph_store` key in `MemoryConfig` and no `enable_graph` flag in the OSS SDKs.
|
||||
|
||||
Graph memory remains a hosted Platform feature. Do not add `graph_store` config, Neo4j/Memgraph/Kuzu/Apache AGE providers, or graph examples to OSS code, docs, or skills. See `3f717e545` for the docs framing.
|
||||
|
||||
+2
-2
@@ -393,8 +393,8 @@ class DependencyError(MemoryError):
|
||||
raise DependencyError(
|
||||
message="Required dependency missing",
|
||||
error_code="DEPS_001",
|
||||
details={"package": "kuzu", "feature": "graph_store"},
|
||||
suggestion="Please install the required dependencies: pip install kuzu"
|
||||
details={"package": "chromadb", "feature": "vector_store"},
|
||||
suggestion="Please install the required dependencies: pip install chromadb"
|
||||
)
|
||||
"""
|
||||
def __init__(self, message: str, error_code: str = "DEPS_001", details: dict = None,
|
||||
|
||||
@@ -54,7 +54,7 @@ After installing, just ask Claude:
|
||||
- "Add memory to my chatbot"
|
||||
- "Help me search user memories with filters"
|
||||
- "Integrate mem0 with my LangChain app"
|
||||
- "Add graph memory to track entity relationships"
|
||||
- "Migrate my app from mem0 v2 to v3"
|
||||
|
||||
## What's Inside
|
||||
|
||||
@@ -74,7 +74,7 @@ skills/mem0/
|
||||
├── sdk-guide.md # All SDK methods (Python + TypeScript)
|
||||
├── api-reference.md # REST endpoints, filters, memory object
|
||||
├── architecture.md # Processing pipeline, lifecycle, scoping, performance
|
||||
├── features.md # Retrieval, graph, categories, MCP, webhooks, multimodal
|
||||
├── features.md # Retrieval, entity linking, categories, MCP, webhooks, multimodal
|
||||
├── integration-patterns.md # LangChain, CrewAI, OpenAI Agents, LangGraph, LlamaIndex, etc.
|
||||
└── use-cases.md # 7 real-world patterns with Python + TypeScript code
|
||||
```
|
||||
|
||||
@@ -36,9 +36,8 @@ SECTION_MAP = {
|
||||
"platform": [
|
||||
"/platform/overview",
|
||||
"/platform/quickstart",
|
||||
"/platform/features",
|
||||
"/platform/features/graph-memory",
|
||||
"/platform/features/selective-memory",
|
||||
"/platform/features/advanced-retrieval",
|
||||
"/platform/features/custom-categories",
|
||||
"/platform/features/v2-memory-filters",
|
||||
"/platform/features/async-client",
|
||||
@@ -57,10 +56,10 @@ SECTION_MAP = {
|
||||
"/open-source/overview",
|
||||
"/open-source/python-quickstart",
|
||||
"/open-source/node-quickstart",
|
||||
"/open-source/features",
|
||||
"/open-source/features/graph-memory",
|
||||
"/open-source/features/overview",
|
||||
"/open-source/features/rest-api",
|
||||
"/open-source/configure-components",
|
||||
"/open-source/features/metadata-filtering",
|
||||
"/open-source/configuration",
|
||||
],
|
||||
"sdks": [
|
||||
"/sdks/python",
|
||||
|
||||
@@ -0,0 +1,37 @@
|
||||
"""Drift test: the provider counts in mem0/AGENTS.md must match the factory registries."""
|
||||
|
||||
import re
|
||||
from pathlib import Path
|
||||
|
||||
import pytest
|
||||
|
||||
from mem0.utils.factory import (
|
||||
EmbedderFactory,
|
||||
LlmFactory,
|
||||
RerankerFactory,
|
||||
VectorStoreFactory,
|
||||
)
|
||||
|
||||
AGENTS_MD = Path(__file__).resolve().parents[1] / "mem0" / "AGENTS.md"
|
||||
|
||||
ROW_TO_FACTORY = {
|
||||
"LLMs": LlmFactory,
|
||||
"Vector stores": VectorStoreFactory,
|
||||
"Embeddings": EmbedderFactory,
|
||||
"Rerankers": RerankerFactory,
|
||||
}
|
||||
|
||||
|
||||
def _documented_count(row_name: str) -> int:
|
||||
match = re.search(rf"^\|\s*{re.escape(row_name)}\s*\|\s*(\d+)\s*\|", AGENTS_MD.read_text(), re.M)
|
||||
return int(match.group(1)) if match else None
|
||||
|
||||
|
||||
@pytest.mark.parametrize("row_name,factory", ROW_TO_FACTORY.items())
|
||||
def test_documented_count_matches_registry(row_name, factory):
|
||||
documented = _documented_count(row_name)
|
||||
assert documented is not None, f"mem0/AGENTS.md provider table has no {row_name!r} row"
|
||||
assert documented == len(factory.provider_to_class), (
|
||||
f"mem0/AGENTS.md says {documented} {row_name} but "
|
||||
f"{factory.__name__}.provider_to_class has {len(factory.provider_to_class)}"
|
||||
)
|
||||
@@ -0,0 +1,27 @@
|
||||
"""Drift test: the tag prefixes in CONTRIBUTING.md must match the router in release.yml."""
|
||||
|
||||
import re
|
||||
from pathlib import Path
|
||||
|
||||
REPO_ROOT = Path(__file__).resolve().parents[1]
|
||||
CONTRIBUTING_MD = REPO_ROOT / "CONTRIBUTING.md"
|
||||
RELEASE_YML = REPO_ROOT / ".github" / "workflows" / "release.yml"
|
||||
|
||||
|
||||
def _documented_prefixes():
|
||||
section = CONTRIBUTING_MD.read_text().split("### Tag Prefixes")[1].split("###")[0]
|
||||
return set(re.findall(r"^\|[^|\n]+\|[^|\n]+\|\s*`([^`\n]+\*)`\s*\|", section, re.M))
|
||||
|
||||
|
||||
def _routed_prefixes():
|
||||
case_block = re.search(r'case "\$TAG" in\n(.*?)\n\s*esac', RELEASE_YML.read_text(), re.S).group(1)
|
||||
return set(re.findall(r"^\s*([\w.-]+\*)\)", case_block, re.M))
|
||||
|
||||
|
||||
def test_documented_prefixes_match_release_router():
|
||||
documented, routed = _documented_prefixes(), _routed_prefixes()
|
||||
assert documented, "CONTRIBUTING.md '### Tag Prefixes' table has no tag prefixes"
|
||||
assert documented == routed, (
|
||||
f"CONTRIBUTING.md documents {sorted(documented - routed)} with no arm in release.yml, "
|
||||
f"and release.yml routes {sorted(routed - documented)} with no row in CONTRIBUTING.md"
|
||||
)
|
||||
@@ -83,7 +83,6 @@ class TestTelemetryEnabled:
|
||||
mock_at = MagicMock()
|
||||
with patch.object(telemetry_module, "_oss_telemetry_instance", mock_at):
|
||||
mock_memory = MagicMock()
|
||||
mock_memory.config.graph_store.config = None
|
||||
mock_memory.api_version = "v1"
|
||||
telemetry_module.capture_event("test.event", mock_memory)
|
||||
mock_at.capture_event.assert_called_once()
|
||||
@@ -223,7 +222,6 @@ class TestTelemetrySingleton:
|
||||
with patch("mem0.memory.telemetry.get_or_create_user_id", return_value="u"):
|
||||
with patch("atexit.register"):
|
||||
mock_memory = MagicMock()
|
||||
mock_memory.config.graph_store.config = None
|
||||
mock_memory.api_version = "v1"
|
||||
|
||||
telemetry_module.capture_event("e1", mock_memory)
|
||||
@@ -242,7 +240,6 @@ class TestTelemetrySingleton:
|
||||
with patch("mem0.memory.telemetry.get_or_create_user_id", return_value="u"):
|
||||
with patch("atexit.register"):
|
||||
mock_memory = MagicMock()
|
||||
mock_memory.config.graph_store.config = None
|
||||
mock_memory.api_version = "v1"
|
||||
|
||||
for i in range(50):
|
||||
@@ -421,7 +418,6 @@ class TestTelemetryNullUserIdHandling:
|
||||
|
||||
with patch.object(telemetry_module, "_oss_telemetry_instance", mock_at):
|
||||
mock_memory = MagicMock()
|
||||
mock_memory.config.graph_store.config = None
|
||||
mock_memory.api_version = "v1"
|
||||
|
||||
# This should not raise, even when telemetry fails
|
||||
|
||||
Reference in New Issue
Block a user