fix: update skills and docs (#4868)
This commit is contained in:
@@ -12,7 +12,7 @@ description: >
|
||||
license: Apache-2.0
|
||||
metadata:
|
||||
author: mem0ai
|
||||
version: "1.0.0"
|
||||
version: "1.1.0"
|
||||
category: ai-memory
|
||||
tags: "cli, terminal, memory, ai, command-line"
|
||||
compatibility: Node.js 18+ (npm install -g @mem0/cli) or Python 3.10+ (pip install mem0-cli), MEM0_API_KEY env var
|
||||
@@ -134,7 +134,6 @@ Choose whichever runtime you already have installed. The behavior is the same.
|
||||
- **`--all` vs `--entity` delete modes:** `mem0 delete --all -u alice` deletes all memories for user alice. `mem0 delete --entity -u alice` deletes the entity itself AND all its memories (cascade). These are mutually exclusive modes.
|
||||
- **Entity ID resolution:** If you pass any explicit scope flag (e.g. `--user-id`), the CLI uses ONLY the explicit IDs and ignores config defaults. If no scope flags are given, all configured defaults apply.
|
||||
- **Stdin detection:** When no text argument is provided and input is piped (not a TTY), the CLI reads from stdin. Works with `add`, `search`, and `update`.
|
||||
- **Graph tri-state:** `--no-graph` takes precedence over `--graph`, which takes precedence over the config default (`defaults.enable_graph`).
|
||||
|
||||
## References
|
||||
|
||||
|
||||
@@ -77,12 +77,8 @@ Add a memory from text, messages, file, or stdin.
|
||||
| `--messages <json>` | string | - | Conversation messages as JSON array (e.g. `'[{"role":"user","content":"..."}]'`). |
|
||||
| `-f, --file <path>` | path | - | Read messages from a JSON file. |
|
||||
| `-m, --metadata <json>` | string | - | Custom metadata as JSON object (e.g. `'{"source":"cli"}'`). |
|
||||
| `--immutable` | boolean | false | Prevent future updates to this memory. |
|
||||
| `--no-infer` | boolean | false | Skip inference; store the text verbatim. |
|
||||
| `--expires <date>` | string | - | Expiration date in `YYYY-MM-DD` format. |
|
||||
| `--categories <cats>` | string | - | Categories as JSON array or comma-separated string. |
|
||||
| `--graph` | boolean | false | Enable graph memory extraction for this call. |
|
||||
| `--no-graph` | boolean | false | Disable graph memory extraction for this call. |
|
||||
| `-o, --output <fmt>` | string | `text` | Output format: `text`, `json`, `quiet`. |
|
||||
|
||||
**Input priority:** `--file` > `--messages` > text argument > stdin (if piped and no text).
|
||||
@@ -134,13 +130,10 @@ Search memories by semantic query.
|
||||
| `--app-id <id>` | string | - | Filter by app. |
|
||||
| `--run-id <id>` | string | - | Filter by run. |
|
||||
| `-k, --top-k, --limit <n>` | integer | 10 | Maximum number of results to return. |
|
||||
| `--threshold <score>` | float | 0.3 | Minimum similarity score (0.0 to 1.0). |
|
||||
| `--threshold <score>` | float | 0.1 | Minimum similarity score (0.0 to 1.0). |
|
||||
| `--rerank` | boolean | false | Enable reranking for improved relevance (Platform only). |
|
||||
| `--keyword` | boolean | false | Use keyword search instead of semantic. |
|
||||
| `--filter <json>` | string | - | Advanced filter expression as JSON (AND/OR operators). |
|
||||
| `--fields <list>` | string | - | Comma-separated list of fields to return. |
|
||||
| `--graph` | boolean | false | Enable graph in search. |
|
||||
| `--no-graph` | boolean | false | Disable graph in search. |
|
||||
| `-o, --output <fmt>` | string | `text` | Output format: `text`, `json`, `table`. |
|
||||
|
||||
**Examples:**
|
||||
@@ -200,8 +193,6 @@ List memories with optional filters and pagination.
|
||||
| `--category <name>` | string | - | Filter by category. |
|
||||
| `--after <date>` | string | - | Created after (YYYY-MM-DD). |
|
||||
| `--before <date>` | string | - | Created before (YYYY-MM-DD). |
|
||||
| `--graph` | boolean | false | Enable graph in listing. |
|
||||
| `--no-graph` | boolean | false | Disable graph in listing. |
|
||||
| `-o, --output <fmt>` | string | `table` | Output format: `text`, `json`, `table`. |
|
||||
|
||||
**Examples:**
|
||||
@@ -373,7 +364,7 @@ Get a single configuration value.
|
||||
|------|------|----------|-------------|
|
||||
| `key` | string | Yes | Dotted config key (e.g. `platform.api_key`, `defaults.user_id`). |
|
||||
|
||||
**Valid keys:** `platform.api_key`, `platform.base_url`, `defaults.user_id`, `defaults.agent_id`, `defaults.app_id`, `defaults.run_id`, `defaults.enable_graph`.
|
||||
**Valid keys:** `platform.api_key`, `platform.base_url`, `defaults.user_id`, `defaults.agent_id`, `defaults.app_id`, `defaults.run_id`.
|
||||
|
||||
API key values are always redacted in output.
|
||||
|
||||
@@ -404,7 +395,6 @@ Set a configuration value.
|
||||
```bash
|
||||
mem0 config set defaults.user_id alice
|
||||
mem0 config set platform.base_url https://api.mem0.ai
|
||||
mem0 config set defaults.enable_graph true
|
||||
```
|
||||
|
||||
---
|
||||
@@ -638,20 +628,6 @@ This applies to commands with `resolveIds: true`: `add`, `search`, `list`, `dele
|
||||
|
||||
---
|
||||
|
||||
## Graph Tri-State
|
||||
|
||||
The `enable_graph` parameter follows a three-level precedence:
|
||||
|
||||
```
|
||||
--no-graph (explicit disable) > --graph (explicit enable) > config default
|
||||
```
|
||||
|
||||
If `--no-graph` is passed, graph is disabled regardless of other settings. If `--graph` is passed (without `--no-graph`), graph is enabled. If neither is passed, the config value `defaults.enable_graph` is used.
|
||||
|
||||
This applies to commands with `resolveGraph: true`: `add`, `search`, `list`.
|
||||
|
||||
---
|
||||
|
||||
## Filter Building
|
||||
|
||||
For `search` and `list`, entity IDs and additional filters are composed into the API filter structure:
|
||||
|
||||
@@ -24,8 +24,7 @@ The restricted permissions ensure API keys are not world-readable.
|
||||
"user_id": "",
|
||||
"agent_id": "",
|
||||
"app_id": "",
|
||||
"run_id": "",
|
||||
"enable_graph": false
|
||||
"run_id": ""
|
||||
},
|
||||
"platform": {
|
||||
"api_key": "",
|
||||
@@ -43,7 +42,6 @@ The restricted permissions ensure API keys are not world-readable.
|
||||
| `defaults.agent_id` | string | `""` | Default agent ID for scoping commands. |
|
||||
| `defaults.app_id` | string | `""` | Default app ID for scoping commands. |
|
||||
| `defaults.run_id` | string | `""` | Default run ID for scoping commands. |
|
||||
| `defaults.enable_graph` | boolean | `false` | Default graph memory extraction toggle. |
|
||||
| `platform.api_key` | string | `""` | API key for the Mem0 Platform. |
|
||||
| `platform.base_url` | string | `"https://api.mem0.ai"` | Base URL for API requests. |
|
||||
|
||||
@@ -127,7 +125,6 @@ Reads a single configuration value. The key uses dotted notation.
|
||||
```bash
|
||||
mem0 config get platform.api_key # prints: m0-x...xxxx (redacted)
|
||||
mem0 config get defaults.user_id # prints: alice
|
||||
mem0 config get defaults.enable_graph # prints: false
|
||||
```
|
||||
|
||||
**Valid keys:**
|
||||
@@ -137,7 +134,6 @@ mem0 config get defaults.enable_graph # prints: false
|
||||
- `defaults.agent_id`
|
||||
- `defaults.app_id`
|
||||
- `defaults.run_id`
|
||||
- `defaults.enable_graph`
|
||||
|
||||
Unknown keys print an error message.
|
||||
|
||||
@@ -148,7 +144,6 @@ Sets a configuration value and saves the config file.
|
||||
```bash
|
||||
mem0 config set defaults.user_id alice
|
||||
mem0 config set platform.base_url https://api.mem0.ai
|
||||
mem0 config set defaults.enable_graph true
|
||||
```
|
||||
|
||||
**Type coercion:**
|
||||
@@ -178,20 +173,6 @@ Environment variables override config file values but are overridden by CLI flag
|
||||
| `MEM0_AGENT_ID` | `defaults.agent_id` | string | `""` |
|
||||
| `MEM0_APP_ID` | `defaults.app_id` | string | `""` |
|
||||
| `MEM0_RUN_ID` | `defaults.run_id` | string | `""` |
|
||||
| `MEM0_ENABLE_GRAPH` | `defaults.enable_graph` | boolean | `false` |
|
||||
|
||||
### Boolean Parsing for `MEM0_ENABLE_GRAPH`
|
||||
|
||||
Accepted truthy values (case-insensitive): `"true"`, `"1"`, `"yes"`. Everything else is treated as `false`.
|
||||
|
||||
```bash
|
||||
export MEM0_ENABLE_GRAPH=true # enabled
|
||||
export MEM0_ENABLE_GRAPH=1 # enabled
|
||||
export MEM0_ENABLE_GRAPH=yes # enabled
|
||||
export MEM0_ENABLE_GRAPH=false # disabled
|
||||
export MEM0_ENABLE_GRAPH=0 # disabled
|
||||
export MEM0_ENABLE_GRAPH="" # disabled
|
||||
```
|
||||
|
||||
---
|
||||
|
||||
@@ -200,8 +181,8 @@ export MEM0_ENABLE_GRAPH="" # disabled
|
||||
Configuration values are resolved in this order (highest priority first):
|
||||
|
||||
```
|
||||
1. CLI flags --api-key, --user-id, --base-url, --graph, --no-graph, etc.
|
||||
2. Environment vars MEM0_API_KEY, MEM0_USER_ID, MEM0_ENABLE_GRAPH, etc.
|
||||
1. CLI flags --api-key, --user-id, --base-url, etc.
|
||||
2. Environment vars MEM0_API_KEY, MEM0_USER_ID, etc.
|
||||
3. Config file ~/.mem0/config.json
|
||||
4. Defaults Hardcoded defaults (empty strings, false, https://api.mem0.ai)
|
||||
```
|
||||
@@ -241,4 +222,3 @@ The `config get` and `config set` commands use dotted key paths. Here is the ful
|
||||
| `defaults.agent_id` | defaults | agent_id |
|
||||
| `defaults.app_id` | defaults | app_id |
|
||||
| `defaults.run_id` | defaults | run_id |
|
||||
| `defaults.enable_graph` | defaults | enable_graph |
|
||||
|
||||
@@ -12,7 +12,7 @@ description: >
|
||||
license: Apache-2.0
|
||||
metadata:
|
||||
author: mem0ai
|
||||
version: "1.0.0"
|
||||
version: "1.1.0"
|
||||
category: ai-memory
|
||||
tags: "vercel, ai-sdk, memory, nextjs, typescript, provider"
|
||||
compatibility: Node.js 18+, npm install @mem0/vercel-ai-provider, Vercel AI SDK v5 (ai package), MEM0_API_KEY + LLM provider API key
|
||||
@@ -47,16 +47,16 @@ import { createMem0 } from "@mem0/vercel-ai-provider";
|
||||
|
||||
const mem0 = createMem0();
|
||||
const { text } = await generateText({
|
||||
model: mem0("gpt-4-turbo", { user_id: "alice" }),
|
||||
model: mem0("gpt-5-mini", { user_id: "alice" }),
|
||||
prompt: "Recommend a restaurant",
|
||||
});
|
||||
```
|
||||
|
||||
What happens under the hood:
|
||||
1. The prompt is sent to Mem0 search (`POST /v2/memories/search/`) to retrieve relevant memories
|
||||
1. The prompt is sent to Mem0 search (`POST /v3/memories/search/`) to retrieve relevant memories
|
||||
2. Retrieved memories are injected as a system message at the start of the prompt
|
||||
3. The underlying LLM (e.g., OpenAI gpt-4-turbo) generates a response using the enriched prompt
|
||||
4. The conversation is stored back to Mem0 (`POST /v1/memories/`) as a fire-and-forget async call (no await)
|
||||
3. The underlying LLM (e.g., OpenAI gpt-5-mini) generates a response using the enriched prompt
|
||||
4. The conversation is stored back to Mem0 (`POST /v3/memories/add/`) as a fire-and-forget async call (no await)
|
||||
|
||||
## Pattern 2: Standalone Utilities
|
||||
|
||||
@@ -77,7 +77,7 @@ const memories = await retrieveMemories(prompt, {
|
||||
|
||||
// Generate using any provider with injected memories
|
||||
const { text } = await generateText({
|
||||
model: openai("gpt-4-turbo"),
|
||||
model: openai("gpt-5-mini"),
|
||||
prompt,
|
||||
system: memories,
|
||||
});
|
||||
@@ -102,7 +102,7 @@ import { createMem0 } from "@mem0/vercel-ai-provider";
|
||||
|
||||
const mem0 = createMem0();
|
||||
const result = streamText({
|
||||
model: mem0("gpt-4-turbo", { user_id: "alice" }),
|
||||
model: mem0("gpt-5-mini", { user_id: "alice" }),
|
||||
prompt: "What should I cook for dinner?",
|
||||
});
|
||||
|
||||
@@ -128,7 +128,7 @@ Select a provider when creating the Mem0 instance:
|
||||
```typescript
|
||||
const mem0 = createMem0({ provider: "anthropic" });
|
||||
const { text } = await generateText({
|
||||
model: mem0("claude-sonnet-4-20250514", { user_id: "alice" }),
|
||||
model: mem0("gpt-5-mini", { user_id: "alice" }),
|
||||
prompt: "Hello!",
|
||||
});
|
||||
```
|
||||
@@ -139,7 +139,7 @@ const { text } = await generateText({
|
||||
|
||||
```
|
||||
User prompt
|
||||
--> searchInternalMemories (POST /v2/memories/search/)
|
||||
--> searchInternalMemories (POST /v3/memories/search/)
|
||||
--> memories injected as system message at start of prompt
|
||||
--> underlying LLM generates response (doGenerate or doStream)
|
||||
--> processMemories fires addMemories as fire-and-forget (no await)
|
||||
@@ -161,7 +161,7 @@ User controls each step:
|
||||
| Function | Returns | Use when |
|
||||
|----------|---------|----------|
|
||||
| `retrieveMemories` | Formatted system prompt **string** | Injecting directly into `system` parameter |
|
||||
| `getMemories` | Raw memory **array** (or full response if `enable_graph`) | Processing memories programmatically |
|
||||
| `getMemories` | Raw memory **array** | Processing memories programmatically |
|
||||
| `searchMemories` | Full search **response** (results + relations) | Need relations, scores, metadata |
|
||||
| `addMemories` | API response | Storing new messages to Mem0 |
|
||||
|
||||
@@ -171,7 +171,6 @@ All four accept `LanguageModelV2Prompt | string` as the first argument and optio
|
||||
|
||||
- **Always provide `user_id`** (or `agent_id`/`app_id`/`run_id`) for consistent memory retrieval. Without an entity identifier, memories cannot be scoped.
|
||||
- **Standalone utilities require explicit API key**: pass `mem0ApiKey` in the config object, or set the `MEM0_API_KEY` environment variable.
|
||||
- **Graph memories**: set `enable_graph: true` in the config to retrieve graph relations alongside text memories. When enabled, `getMemories` returns the full response (with `results` and `relations`), not just the array.
|
||||
- **This uses Vercel AI SDK v5** (LanguageModelV2 / ProviderV2 interfaces). It is not compatible with AI SDK v3 or v4.
|
||||
- **`processMemories` fires `addMemories` as fire-and-forget** (`.then()` without `await`). Memory storage happens asynchronously and does not block the LLM response.
|
||||
- **The `"gemini"` alias** exists in the provider switch but is NOT in the `supportedProviders` list. Use `"google"` instead.
|
||||
|
||||
@@ -79,8 +79,7 @@ async function retrieveMemories(
|
||||
1. Flattens the prompt to a plain string (extracts text from `LanguageModelV2Prompt` parts)
|
||||
2. Calls `searchInternalMemories` (`POST /v2/memories/search/`)
|
||||
3. Formats each memory as `"Memory: {memory.memory}\n\n"`
|
||||
4. If `enable_graph: true`, also appends graph relations as `"Relation: {source} -> {relationship} -> {target}\n\n"`
|
||||
5. Wraps everything in a system prompt preamble
|
||||
4. Wraps everything in a system prompt preamble
|
||||
|
||||
**Returns:** A **string** containing the formatted system prompt with embedded memories. Returns `""` (empty string) if no memories found.
|
||||
|
||||
@@ -91,17 +90,13 @@ System Message: These are the memories I have stored. Give more weightage to the
|
||||
Memory: User loves Italian food
|
||||
|
||||
Memory: User is vegetarian
|
||||
|
||||
HERE ARE THE GRAPHS RELATIONS FOR THE PREFERENCES OF THE USER:
|
||||
|
||||
Relation: Alice -> likes -> Italian cuisine
|
||||
```
|
||||
|
||||
---
|
||||
|
||||
## `getMemories(prompt, config?)`
|
||||
|
||||
Retrieves memories and returns the **raw memory array** (or full response if graph is enabled).
|
||||
Retrieves memories and returns the **raw memory array**.
|
||||
|
||||
```typescript
|
||||
import { getMemories } from "@mem0/vercel-ai-provider";
|
||||
@@ -111,14 +106,6 @@ const memories = await getMemories("What are my preferences?", {
|
||||
mem0ApiKey: "m0-xxx",
|
||||
});
|
||||
// Returns: [{ memory: "User loves Italian food", id: "...", ... }, ...]
|
||||
|
||||
// With graph enabled:
|
||||
const graphMemories = await getMemories("What are my preferences?", {
|
||||
user_id: "alice",
|
||||
mem0ApiKey: "m0-xxx",
|
||||
enable_graph: true,
|
||||
});
|
||||
// Returns: { results: [...], relations: [...] }
|
||||
```
|
||||
|
||||
**Signature:**
|
||||
@@ -140,10 +127,9 @@ async function getMemories(
|
||||
**Behavior:**
|
||||
1. Flattens the prompt to a plain string
|
||||
2. Calls `searchInternalMemories` (`POST /v2/memories/search/`)
|
||||
3. If `enable_graph` is **not** set: returns `memories.results` (the array of memory objects)
|
||||
4. If `enable_graph` is set: returns the full response object (with both `results` and `relations`)
|
||||
3. Returns `memories.results` (the array of memory objects)
|
||||
|
||||
**Returns:** Memory object array, or full response object when graph is enabled.
|
||||
**Returns:** Memory object array.
|
||||
|
||||
---
|
||||
|
||||
@@ -184,7 +170,7 @@ async function searchMemories(
|
||||
|
||||
**Returns:** The complete API response object. On error, returns `[]`.
|
||||
|
||||
**Note:** Unlike `getMemories`, this always returns the full response regardless of `enable_graph` setting.
|
||||
**Note:** Unlike `getMemories`, this always returns the full response.
|
||||
|
||||
---
|
||||
|
||||
@@ -193,8 +179,8 @@ async function searchMemories(
|
||||
| Function | Returns | Use when |
|
||||
|----------|---------|----------|
|
||||
| `retrieveMemories` | Formatted system prompt **string** | Injecting directly into a `system` parameter for `generateText`/`streamText` |
|
||||
| `getMemories` | Memory **array** (or full response if `enable_graph`) | Processing memories programmatically (filtering, transforming, counting) |
|
||||
| `searchMemories` | Full API **response** (results + relations) | Need relations, similarity scores, or complete metadata regardless of graph setting |
|
||||
| `getMemories` | Memory **array** | Processing memories programmatically (filtering, transforming, counting) |
|
||||
| `searchMemories` | Full API **response** (results + relations) | Need relations, similarity scores, or complete metadata |
|
||||
| `addMemories` | API response | Storing new conversation messages as memories |
|
||||
|
||||
## Internal: `searchInternalMemories(query, config?, top_k?)`
|
||||
@@ -210,15 +196,13 @@ async function searchInternalMemories(
|
||||
```
|
||||
|
||||
**Behavior:**
|
||||
1. Builds an `OR` filter from entity identifiers (`user_id`, `app_id`, `agent_id`, `run_id`)
|
||||
2. Resolves org/project identifiers (`org_id` takes precedence over `org_name`)
|
||||
1. Builds a `filters` object from entity identifiers (`user_id`, `app_id`, `agent_id`, `run_id`)
|
||||
2. Resolves entity identifiers
|
||||
3. Loads the API key from `config.mem0ApiKey` or `MEM0_API_KEY` env var
|
||||
4. Calls `POST {host}/v2/memories/search/` with:
|
||||
- `query`: the search string
|
||||
- `filters`: the OR filter object
|
||||
- `filters`: the filter object with entity identifiers
|
||||
- `top_k`: from config or default 5
|
||||
- `version`: `"v2"`
|
||||
- `output_format`: `"v1.1"`
|
||||
- All other config fields spread into the request body
|
||||
|
||||
**Default host:** `https://api.mem0.ai`
|
||||
@@ -264,10 +248,6 @@ All fields are optional. Used across all utility functions.
|
||||
| `app_id` | `string` | -- | Scope memories to an application |
|
||||
| `agent_id` | `string` | -- | Scope memories to an agent |
|
||||
| `run_id` | `string` | -- | Scope memories to a session/run |
|
||||
| `org_name` | `string` | -- | Organization name (fallback if `org_id` not set) |
|
||||
| `project_name` | `string` | -- | Project name (fallback if `org_id` not set) |
|
||||
| `org_id` | `string` | -- | Organization ID (takes precedence) |
|
||||
| `project_id` | `string` | -- | Project ID |
|
||||
| `metadata` | `Record<string, any>` | -- | Custom metadata |
|
||||
| `filters` | `Record<string, any>` | -- | Custom search filters |
|
||||
| `infer` | `boolean` | -- | Enable inference |
|
||||
@@ -277,8 +257,4 @@ All fields are optional. Used across all utility functions.
|
||||
| `top_k` | `number` | `5` | Number of memories to retrieve |
|
||||
| `threshold` | `number` | -- | Minimum similarity score |
|
||||
| `rerank` | `boolean` | -- | Enable re-ranking |
|
||||
| `enable_graph` | `boolean` | -- | Enable graph memory (relations) |
|
||||
| `host` | `string` | `https://api.mem0.ai` | Custom API host |
|
||||
| `output_format` | `string` | -- | Output format version |
|
||||
| `filter_memories` | `boolean` | -- | Enable memory filtering |
|
||||
| `async_mode` | `boolean` | -- | Enable async processing |
|
||||
|
||||
@@ -9,8 +9,8 @@ Factory function that creates a `Mem0Provider` instance. This is the primary ent
|
||||
```typescript
|
||||
import { createMem0 } from "@mem0/vercel-ai-provider";
|
||||
|
||||
const mem0 = createMem0(); // defaults: provider "openai"
|
||||
const mem0 = createMem0({ provider: "anthropic" }); // use Anthropic as LLM backend
|
||||
const mem0 = createMem0(); // defaults: provider "openai"
|
||||
const mem0 = createMem0({ provider: "anthropic" }); // use Anthropic as LLM backend
|
||||
```
|
||||
|
||||
**Signature:**
|
||||
@@ -39,7 +39,7 @@ interface Mem0Provider extends ProviderV2 {
|
||||
}
|
||||
```
|
||||
|
||||
- **Direct call** (`mem0("gpt-4-turbo", {...})`): creates a generic language model (neither chat nor completion mode forced).
|
||||
- **Direct call** (`mem0("gpt-5-mini", {...})`): creates a generic language model (neither chat nor completion mode forced).
|
||||
- **`chat()`**: creates a model with `modelType: "chat"` (note: in the current source, the chat constructor sets `modelType: "completion"` -- this appears to be a bug; functionally equivalent to `completion()` at present).
|
||||
- **`completion()`**: creates a model with `modelType: "completion"`.
|
||||
- **`languageModel()`**: alias for the generic model (same as direct call).
|
||||
@@ -73,7 +73,7 @@ interface Mem0ProviderSettings {
|
||||
| `provider` | Which LLM backend to use | `"openai"`, `"anthropic"`, `"google"`, `"groq"`, `"cohere"` |
|
||||
| `mem0ApiKey` | Mem0 Platform API key | `"m0-xxx"` |
|
||||
| `apiKey` | LLM provider API key | `"sk-xxx"` (OpenAI), `"sk-ant-xxx"` (Anthropic) |
|
||||
| `mem0Config` | Default Mem0 settings for all calls | `{ user_id: "alice", enable_graph: true }` |
|
||||
| `mem0Config` | Default Mem0 settings for all calls | `{ user_id: "alice" }` |
|
||||
| `config` | Provider-specific SDK settings | `{ organization: "org-xxx" }` for OpenAI |
|
||||
| `baseURL` | Override LLM provider base URL | `"https://my-proxy.example.com"` |
|
||||
|
||||
@@ -85,7 +85,7 @@ A pre-configured instance using default settings (OpenAI provider, no API keys s
|
||||
import { mem0 } from "@mem0/vercel-ai-provider";
|
||||
|
||||
const { text } = await generateText({
|
||||
model: mem0("gpt-4-turbo", { user_id: "alice" }),
|
||||
model: mem0("gpt-5-mini", { user_id: "alice" }),
|
||||
prompt: "Hello",
|
||||
});
|
||||
```
|
||||
@@ -102,10 +102,6 @@ interface Mem0ConfigSettings {
|
||||
app_id?: string; // Scope memories to an application
|
||||
agent_id?: string; // Scope memories to an agent
|
||||
run_id?: string; // Scope memories to a specific run/session
|
||||
org_name?: string; // Organization name (used if org_id not set)
|
||||
project_name?: string; // Project name (used if org_id not set)
|
||||
org_id?: string; // Organization ID (takes precedence over org_name)
|
||||
project_id?: string; // Project ID (takes precedence over project_name)
|
||||
metadata?: Record<string, any>; // Custom metadata attached to memories
|
||||
filters?: Record<string, any>; // Custom filters for memory search
|
||||
infer?: boolean; // Enable inference during memory operations
|
||||
@@ -113,13 +109,9 @@ interface Mem0ConfigSettings {
|
||||
page_size?: number; // Pagination: results per page
|
||||
mem0ApiKey?: string; // Mem0 API key (overrides provider-level key)
|
||||
top_k?: number; // Number of memories to retrieve (default: 5)
|
||||
threshold?: number; // Minimum similarity score for retrieval
|
||||
rerank?: boolean; // Enable re-ranking of search results
|
||||
enable_graph?: boolean; // Enable graph memory (returns relations)
|
||||
threshold?: number; // Minimum similarity score for retrieval (default: 0.1)
|
||||
rerank?: boolean; // Enable re-ranking of search results (default: false)
|
||||
host?: string; // Custom Mem0 API host (default: "https://api.mem0.ai")
|
||||
output_format?: string; // Output format version
|
||||
filter_memories?: boolean; // Enable memory filtering
|
||||
async_mode?: boolean; // Enable async processing of memory operations
|
||||
}
|
||||
```
|
||||
|
||||
@@ -138,9 +130,9 @@ This means a `Mem0ChatConfig` has all fields from both `Mem0ConfigSettings` and
|
||||
Alias for `Mem0ConfigSettings`. Passed as the second argument when creating a model:
|
||||
|
||||
```typescript
|
||||
mem0("gpt-4-turbo", { user_id: "alice", enable_graph: true })
|
||||
// ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^
|
||||
// This object is Mem0ChatSettings
|
||||
mem0("gpt-5-mini", { user_id: "alice" })
|
||||
// ^^^^^^^^^^^^^^^^^^
|
||||
// This object is Mem0ChatSettings
|
||||
```
|
||||
|
||||
## `LLMProviderSettings` Type
|
||||
@@ -188,8 +180,8 @@ An alternative exported class that creates models directly without the callable-
|
||||
import { Mem0 } from "@mem0/vercel-ai-provider";
|
||||
|
||||
const mem0 = new Mem0({ provider: "openai" });
|
||||
const chatModel = mem0.chat("gpt-4-turbo", { user_id: "alice" });
|
||||
const completionModel = mem0.completion("gpt-3.5-turbo-instruct");
|
||||
const chatModel = mem0.chat("gpt-5-mini", { user_id: "alice" });
|
||||
const completionModel = mem0.completion("gpt-5-mini");
|
||||
```
|
||||
|
||||
The facade defaults its base URL to `"http://127.0.0.1:11434/api"` (Ollama-style) rather than `"http://api.openai.com"`. It always uses `"openai"` as the provider for created models.
|
||||
@@ -210,7 +202,7 @@ class Mem0GenericLanguageModel implements LanguageModelV2 {
|
||||
readonly supportedUrls: Record<string, RegExp[]> = { '*': [/.*/] };
|
||||
|
||||
provider: string; // e.g., "openai"
|
||||
modelId: string; // e.g., "gpt-4-turbo"
|
||||
modelId: string; // e.g., "gpt-5-mini"
|
||||
settings: Mem0ChatSettings;
|
||||
config: Mem0ChatConfig;
|
||||
|
||||
@@ -230,10 +222,12 @@ Both `doGenerate` and `doStream` follow the same internal flow:
|
||||
4. Delegate to the underlying model's `doGenerate` or `doStream`
|
||||
5. Return the result
|
||||
|
||||
**Note:** Entity identifier fields use snake_case (`user_id`, `app_id`, `agent_id`, `run_id`) to match the Mem0 API.
|
||||
|
||||
## Type: `Mem0ChatModelId`
|
||||
|
||||
```typescript
|
||||
type Mem0ChatModelId = string & NonNullable<unknown>;
|
||||
```
|
||||
|
||||
Any non-null string. The model ID is passed through to the underlying provider (e.g., `"gpt-4-turbo"`, `"claude-sonnet-4-20250514"`, `"gemini-pro"`).
|
||||
Any non-null string. The model ID is passed through to the underlying provider (e.g., `"gpt-5-mini"`, `"gemini-pro"`).
|
||||
|
||||
@@ -13,7 +13,7 @@ import { createMem0 } from "@mem0/vercel-ai-provider";
|
||||
const mem0 = createMem0();
|
||||
|
||||
const { text } = await generateText({
|
||||
model: mem0("gpt-4-turbo", { user_id: "alice" }),
|
||||
model: mem0("gpt-5-mini", { user_id: "alice" }),
|
||||
prompt: "Recommend a restaurant based on my preferences",
|
||||
});
|
||||
|
||||
@@ -33,7 +33,7 @@ import { createMem0 } from "@mem0/vercel-ai-provider";
|
||||
const mem0 = createMem0();
|
||||
|
||||
const result = streamText({
|
||||
model: mem0("gpt-4-turbo", { user_id: "alice" }),
|
||||
model: mem0("gpt-5-mini", { user_id: "alice" }),
|
||||
prompt: "What should I cook for dinner tonight?",
|
||||
});
|
||||
|
||||
@@ -53,17 +53,17 @@ import { openai } from "@ai-sdk/openai";
|
||||
import { generateText } from "ai";
|
||||
import { retrieveMemories, addMemories } from "@mem0/vercel-ai-provider";
|
||||
|
||||
const userId = "alice";
|
||||
const user_id = "alice";
|
||||
const prompt = "Suggest a weekend trip";
|
||||
|
||||
// Step 1: Retrieve memories as a formatted system prompt
|
||||
const memories = await retrieveMemories(prompt, {
|
||||
user_id: userId,
|
||||
user_id: user_id,
|
||||
});
|
||||
|
||||
// Step 2: Generate with the memories injected as system context
|
||||
const { text } = await generateText({
|
||||
model: openai("gpt-4-turbo"),
|
||||
model: openai("gpt-5-mini"),
|
||||
prompt,
|
||||
system: memories,
|
||||
});
|
||||
@@ -76,7 +76,7 @@ await addMemories(
|
||||
{ role: "user", content: [{ type: "text", text: prompt }] },
|
||||
{ role: "assistant", content: [{ type: "text", text }] },
|
||||
],
|
||||
{ user_id: userId }
|
||||
{ user_id: user_id }
|
||||
);
|
||||
```
|
||||
|
||||
@@ -121,7 +121,7 @@ import { z } from "zod";
|
||||
const mem0 = createMem0();
|
||||
|
||||
const { object } = await generateObject({
|
||||
model: mem0("gpt-4-turbo", { user_id: "alice" }),
|
||||
model: mem0("gpt-5-mini", { user_id: "alice" }),
|
||||
prompt: "Suggest a meal plan for today",
|
||||
schema: z.object({
|
||||
breakfast: z.string(),
|
||||
@@ -138,53 +138,7 @@ console.log(object);
|
||||
|
||||
The `defaultObjectGenerationMode` is `"json"`, so structured output works out of the box.
|
||||
|
||||
## 6. Graph Memory Enabled
|
||||
|
||||
Retrieve both text memories and entity relationship graphs.
|
||||
|
||||
```typescript
|
||||
import { generateText } from "ai";
|
||||
import { createMem0 } from "@mem0/vercel-ai-provider";
|
||||
|
||||
const mem0 = createMem0();
|
||||
|
||||
const { text } = await generateText({
|
||||
model: mem0("gpt-4-turbo", {
|
||||
user_id: "alice",
|
||||
enable_graph: true,
|
||||
}),
|
||||
prompt: "What connections do you know about between my friends?",
|
||||
});
|
||||
|
||||
console.log(text);
|
||||
```
|
||||
|
||||
With `enable_graph: true`, the system prompt includes both:
|
||||
- **Text memories**: `"Memory: Alice is friends with Bob"`
|
||||
- **Graph relations**: `"Relation: Alice -> friends_with -> Bob"`
|
||||
|
||||
### Using graph with standalone utilities
|
||||
|
||||
```typescript
|
||||
import { getMemories, searchMemories } from "@mem0/vercel-ai-provider";
|
||||
|
||||
// getMemories with graph returns the full response
|
||||
const graphResult = await getMemories("my social connections", {
|
||||
user_id: "alice",
|
||||
enable_graph: true,
|
||||
});
|
||||
console.log(graphResult.results); // memory objects
|
||||
console.log(graphResult.relations); // graph relations
|
||||
|
||||
// searchMemories always returns the full response
|
||||
const fullResponse = await searchMemories("my social connections", {
|
||||
user_id: "alice",
|
||||
});
|
||||
console.log(fullResponse.results);
|
||||
console.log(fullResponse.relations);
|
||||
```
|
||||
|
||||
## 7. Multi-Provider Setup
|
||||
## 6. Multi-Provider Setup
|
||||
|
||||
Configure different LLM providers with the wrapped model.
|
||||
|
||||
@@ -194,7 +148,7 @@ Configure different LLM providers with the wrapped model.
|
||||
import { createMem0 } from "@mem0/vercel-ai-provider";
|
||||
|
||||
const mem0 = createMem0(); // defaults to "openai"
|
||||
const model = mem0("gpt-4-turbo", { user_id: "alice" });
|
||||
const model = mem0("gpt-5-mini", { user_id: "alice" });
|
||||
```
|
||||
|
||||
### Anthropic
|
||||
@@ -235,7 +189,7 @@ const mem0 = createMem0({
|
||||
});
|
||||
```
|
||||
|
||||
## 8. Next.js API Route Integration
|
||||
## 7. Next.js API Route Integration
|
||||
|
||||
A POST handler that uses the wrapped model in a Next.js App Router API route.
|
||||
|
||||
@@ -247,12 +201,12 @@ import { createMem0 } from "@mem0/vercel-ai-provider";
|
||||
const mem0 = createMem0();
|
||||
|
||||
export async function POST(req: Request) {
|
||||
const { messages, userId } = await req.json();
|
||||
const { messages, user_id } = await req.json();
|
||||
|
||||
const lastMessage = messages[messages.length - 1];
|
||||
|
||||
const result = streamText({
|
||||
model: mem0("gpt-4-turbo", { user_id: userId }),
|
||||
model: mem0("gpt-5-mini", { user_id }),
|
||||
prompt: lastMessage.content,
|
||||
});
|
||||
|
||||
@@ -269,17 +223,17 @@ import { streamText } from "ai";
|
||||
import { retrieveMemories, addMemories } from "@mem0/vercel-ai-provider";
|
||||
|
||||
export async function POST(req: Request) {
|
||||
const { messages, userId } = await req.json();
|
||||
const { messages, user_id } = await req.json();
|
||||
const lastMessage = messages[messages.length - 1];
|
||||
|
||||
// Retrieve relevant memories
|
||||
const memories = await retrieveMemories(lastMessage.content, {
|
||||
user_id: userId,
|
||||
user_id,
|
||||
});
|
||||
|
||||
// Stream the response
|
||||
const result = streamText({
|
||||
model: openai("gpt-4-turbo"),
|
||||
model: openai("gpt-5-mini"),
|
||||
prompt: lastMessage.content,
|
||||
system: memories,
|
||||
});
|
||||
@@ -291,7 +245,7 @@ export async function POST(req: Request) {
|
||||
{ role: "user", content: [{ type: "text", text: lastMessage.content }] },
|
||||
{ role: "assistant", content: [{ type: "text", text }] },
|
||||
],
|
||||
{ user_id: userId }
|
||||
{ user_id }
|
||||
);
|
||||
});
|
||||
|
||||
@@ -299,7 +253,7 @@ export async function POST(req: Request) {
|
||||
}
|
||||
```
|
||||
|
||||
## 9. How Memory Processing Works Internally
|
||||
## 8. How Memory Processing Works Internally
|
||||
|
||||
### Wrapped model flow (doGenerate / doStream)
|
||||
|
||||
@@ -308,10 +262,10 @@ export async function POST(req: Request) {
|
||||
2. processMemories(messagesPrompts, mem0Config):
|
||||
a. addMemories(messagesPrompts, mem0Config)
|
||||
--> fire-and-forget: .then().catch(), NO await
|
||||
--> POST /v1/memories/ with converted messages
|
||||
--> POST /v3/memories/add/ with converted messages
|
||||
b. await getMemories(messagesPrompts, mem0Config)
|
||||
--> POST /v2/memories/search/ with flattened prompt
|
||||
--> returns memory array (or {results, relations} if enable_graph)
|
||||
--> POST /v3/memories/search/ with flattened prompt
|
||||
--> returns memory array
|
||||
c. Format memories into system message string
|
||||
d. Prepend system message to messagesPrompts array
|
||||
e. Return { memories, messagesPrompts }
|
||||
@@ -337,7 +291,7 @@ The memories are injected as a system message at position 0 of the prompt array:
|
||||
}
|
||||
```
|
||||
|
||||
## 10. Custom Configuration
|
||||
## 9. Custom Configuration
|
||||
|
||||
### Custom Mem0 API host
|
||||
|
||||
@@ -358,32 +312,15 @@ const memories = await retrieveMemories(prompt, {
|
||||
});
|
||||
```
|
||||
|
||||
### Organization and project scoping
|
||||
|
||||
```typescript
|
||||
const mem0 = createMem0();
|
||||
const { text } = await generateText({
|
||||
model: mem0("gpt-4-turbo", {
|
||||
user_id: "alice",
|
||||
org_id: "org-123",
|
||||
project_id: "proj-456",
|
||||
}),
|
||||
prompt: "Hello",
|
||||
});
|
||||
```
|
||||
|
||||
Note: `org_id` takes precedence over `org_name`. If `org_id` is set, `org_name` and `project_name` are not sent in the request.
|
||||
|
||||
### Memory filtering and ranking
|
||||
|
||||
```typescript
|
||||
const mem0 = createMem0();
|
||||
const model = mem0("gpt-4-turbo", {
|
||||
const model = mem0("gpt-5-mini", {
|
||||
user_id: "alice",
|
||||
top_k: 10, // retrieve up to 10 memories (default: 5)
|
||||
threshold: 0.8, // only memories with score >= 0.8
|
||||
rerank: true, // enable re-ranking of results
|
||||
filter_memories: true,
|
||||
rerank: true, // enable re-ranking of results
|
||||
});
|
||||
```
|
||||
|
||||
@@ -409,14 +346,13 @@ Set defaults at the provider level that apply to every model created:
|
||||
const mem0 = createMem0({
|
||||
mem0Config: {
|
||||
user_id: "alice",
|
||||
enable_graph: true,
|
||||
top_k: 10,
|
||||
},
|
||||
});
|
||||
|
||||
// These calls inherit user_id, enable_graph, and top_k from mem0Config
|
||||
// These calls inherit user_id and top_k from mem0Config
|
||||
const { text } = await generateText({
|
||||
model: mem0("gpt-4-turbo"),
|
||||
model: mem0("gpt-5-mini"),
|
||||
prompt: "Hello",
|
||||
});
|
||||
```
|
||||
@@ -425,7 +361,7 @@ Per-call settings (passed as the second argument to `mem0()`) are merged on top
|
||||
|
||||
```typescript
|
||||
// Override user_id for this specific call
|
||||
const model = mem0("gpt-4-turbo", { user_id: "bob" });
|
||||
const model = mem0("gpt-5-mini", { user_id: "bob" });
|
||||
```
|
||||
|
||||
The merge order is: `config.mem0Config` (provider defaults) < `settings` (per-call overrides).
|
||||
|
||||
+17
-8
@@ -15,10 +15,10 @@ description: >
|
||||
license: Apache-2.0
|
||||
metadata:
|
||||
author: mem0ai
|
||||
version: "2.0.0"
|
||||
version: "3.0.0"
|
||||
category: ai-memory
|
||||
tags: "memory, personalization, ai, python, typescript, vector-search"
|
||||
compatibility: Requires Python 3.10+ or Node.js 18+, pip install mem0ai or npm install mem0ai, MEM0_API_KEY env var (Platform), and internet access to api.mem0.ai
|
||||
compatibility: Requires Python 3.10+ or Node.js 18+, pip install mem0ai or npm install mem0ai, MEM0_API_KEY env var (Platform), and internet access to api.mem0.ai. SDK v3 with v2 compatibility mode available.
|
||||
---
|
||||
|
||||
# Mem0 Platform Integration
|
||||
@@ -77,14 +77,14 @@ client.add(messages, user_id="alice")
|
||||
|
||||
### Search memories
|
||||
```python
|
||||
results = client.search("dietary preferences", user_id="alice")
|
||||
results = client.search("dietary preferences", filters={"user_id": "alice"})
|
||||
for mem in results.get("results", []):
|
||||
print(mem["memory"])
|
||||
```
|
||||
|
||||
### Get all memories
|
||||
```python
|
||||
all_memories = client.get_all(user_id="alice")
|
||||
all_memories = client.get_all(filters={"user_id": "alice"})
|
||||
```
|
||||
|
||||
### Update a memory
|
||||
@@ -109,12 +109,12 @@ openai = OpenAI()
|
||||
|
||||
def chat(user_input: str, user_id: str) -> str:
|
||||
# 1. Retrieve relevant memories
|
||||
memories = mem0.search(user_input, user_id=user_id)
|
||||
memories = mem0.search(user_input, filters={"user_id": user_id})
|
||||
context = "\n".join([m["memory"] for m in memories.get("results", [])])
|
||||
|
||||
# 2. Generate response with memory context
|
||||
response = openai.chat.completions.create(
|
||||
model="gpt-4.1-nano-2025-04-14",
|
||||
model="gpt-5-mini",
|
||||
messages=[
|
||||
{"role": "system", "content": f"User context:\n{context}"},
|
||||
{"role": "user", "content": user_input},
|
||||
@@ -132,11 +132,20 @@ def chat(user_input: str, user_id: str) -> str:
|
||||
|
||||
## Common edge cases
|
||||
|
||||
- **Search returns empty:** Memories process asynchronously. Wait 2-3s after `add()` before searching. Also verify `user_id` matches exactly (case-sensitive).
|
||||
- **Search returns empty:** Memories process asynchronously. Wait 2-3s after `add()` before searching. Also verify `user_id` matches exactly (case-sensitive) and use `filters={"user_id": "..."}` syntax.
|
||||
- **AND filter with user_id + agent_id returns empty:** Entities are stored separately. Use `OR` instead, or query separately.
|
||||
- **Duplicate memories:** Don't mix `infer=True` (default) and `infer=False` for the same data. Stick to one mode.
|
||||
- **Wrong import:** Always use `from mem0 import MemoryClient` (or `AsyncMemoryClient` for async). Do not use `from mem0 import Memory`.
|
||||
- **Immutable memories:** Cannot be updated or deleted once created. Use `client.history(memory_id)` to track changes over time.
|
||||
- **v3 defaults:** `top_k=20`, `threshold=0.1`, `rerank=False`. Adjust as needed for your use case.
|
||||
|
||||
## v2 Compatibility
|
||||
|
||||
If you're using SDK v2.x, note these differences:
|
||||
- **Entity IDs:** Pass `user_id` as top-level kwarg to `search()` instead of inside `filters`
|
||||
- **Defaults:** `top_k=100`, no threshold, `rerank=True`
|
||||
- **Graph memory:** Available via `enable_graph=True`
|
||||
|
||||
See the [migration guide](https://docs.mem0.ai/migration/oss-v2-to-v3) for details.
|
||||
|
||||
## Live documentation search
|
||||
|
||||
|
||||
@@ -46,18 +46,16 @@ Both read from `MEM0_API_KEY` env var if no key provided.
|
||||
```python
|
||||
# Python: kwargs
|
||||
client.add(messages, user_id="alice", metadata={"source": "chat"})
|
||||
client.search("query", user_id="alice", top_k=5, rerank=True)
|
||||
client.search("query", filters={"user_id": "alice"}, top_k=5, rerank=True)
|
||||
```
|
||||
|
||||
```typescript
|
||||
// TypeScript: options object
|
||||
await client.add(messages, { user_id: 'alice', metadata: { source: 'chat' } });
|
||||
await client.search('query', { user_id: 'alice', top_k: 5, rerank: true });
|
||||
// TypeScript: options object with camelCase for top-level params, snake_case for filter keys
|
||||
await client.add(messages, { userId: 'alice', metadata: { source: 'chat' } });
|
||||
await client.search('query', { filters: { user_id: 'alice' }, topK: 5, rerank: true });
|
||||
```
|
||||
|
||||
**Important:** Both use `snake_case` for API parameter names (`user_id`, `agent_id`, `top_k`, etc.). Only method names differ.
|
||||
|
||||
Exception: OSS TypeScript uses `camelCase` for config params (`userId`, `agentId`, `runId`).
|
||||
**v3:** Python uses `snake_case` everywhere. TypeScript uses `camelCase` for top-level params (`userId`, `topK`) but `snake_case` for filter keys (`user_id`, `agent_id`).
|
||||
|
||||
## Architectural Differences
|
||||
|
||||
@@ -97,10 +95,8 @@ These methods exist in Python but not TypeScript:
|
||||
| Python config key | TypeScript config key |
|
||||
|-------------------|----------------------|
|
||||
| `vector_store` | `vectorStore` |
|
||||
| `graph_store` | `graphStore` |
|
||||
| `history_db_path` | `historyDbPath` |
|
||||
| `custom_instructions` | `customInstructions` |
|
||||
| `enable_graph` | `enableGraph` |
|
||||
|
||||
## OSS Scope Parameter Naming
|
||||
|
||||
@@ -110,16 +106,24 @@ These methods exist in Python but not TypeScript:
|
||||
| `agent_id="bot"` | `agentId: 'bot'` |
|
||||
| `run_id="session"` | `runId: 'session'` |
|
||||
|
||||
## Entity ID Passing (v3)
|
||||
|
||||
| Method | Python | TypeScript |
|
||||
|--------|--------|------------|
|
||||
| add() | Top-level: `user_id="alice"` | Top-level: `{ userId: 'alice' }` |
|
||||
| search() | In filters: `filters={"user_id": "alice"}` | In filters: `{ filters: { user_id: 'alice' } }` |
|
||||
| get_all() | In filters: `filters={"user_id": "alice"}` | In filters: `{ filters: { user_id: 'alice' } }` |
|
||||
|
||||
## Common Gotcha
|
||||
|
||||
When searching/filtering, **both SDKs use `snake_case`** for filter keys:
|
||||
When searching/filtering, both Python and TypeScript use `snake_case` for filter keys. TypeScript only uses `camelCase` for top-level method parameters:
|
||||
|
||||
```python
|
||||
# Python
|
||||
filters = {"AND": [{"user_id": "alice"}, {"categories": {"contains": "health"}}]}
|
||||
# Python - snake_case in filters
|
||||
results = client.search("query", filters={"user_id": "alice"})
|
||||
```
|
||||
|
||||
```typescript
|
||||
// TypeScript -- same snake_case in filter objects!
|
||||
const filters = { AND: [{ user_id: 'alice' }, { categories: { contains: 'health' } }] };
|
||||
// TypeScript - snake_case in filters, camelCase for top-level params
|
||||
const results = await client.search('query', { filters: { user_id: 'alice' }, topK: 20 });
|
||||
```
|
||||
|
||||
+75
-69
@@ -41,23 +41,18 @@ const messages = [
|
||||
{ role: 'user', content: "I'm a vegetarian and allergic to nuts." },
|
||||
{ role: 'assistant', content: "Got it! I'll remember that." },
|
||||
];
|
||||
await client.add(messages, { user_id: 'alice' });
|
||||
await client.add(messages, { userId: 'alice' });
|
||||
```
|
||||
|
||||
| Parameter | Type | Description |
|
||||
|-----------|------|-------------|
|
||||
| `messages` | `Message[]` | Array of `{role, content}` objects |
|
||||
| `options.user_id` | string | User identifier |
|
||||
| `options.agent_id` | string | Agent identifier |
|
||||
| `options.app_id` | string | Application identifier |
|
||||
| `options.run_id` | string | Session identifier |
|
||||
| `options.userId` | string | User identifier |
|
||||
| `options.agentId` | string | Agent identifier |
|
||||
| `options.appId` | string | Application identifier |
|
||||
| `options.runId` | string | Session identifier |
|
||||
| `options.metadata` | object | Custom key-value pairs |
|
||||
| `options.enable_graph` | boolean | Activate knowledge graph |
|
||||
| `options.infer` | boolean | If false, store raw text (default: true) |
|
||||
| `options.immutable` | boolean | Prevent future modification |
|
||||
| `options.expiration_date` | string | Auto-expiry (`YYYY-MM-DD`) |
|
||||
| `options.includes` | string | Preference filter for inclusion |
|
||||
| `options.excludes` | string | Preference filter for exclusion |
|
||||
|
||||
**Returns:** `Promise<any>` -- list of events
|
||||
|
||||
@@ -66,7 +61,7 @@ await client.add(messages, { user_id: 'alice' });
|
||||
Search memories by semantic similarity.
|
||||
|
||||
```typescript
|
||||
const results = await client.search('dietary preferences', { user_id: 'alice' });
|
||||
const results = await client.search('dietary preferences', { filters: { user_id: 'alice' }, topK: 20 });
|
||||
for (const mem of results.results) {
|
||||
console.log(mem.memory, mem.score);
|
||||
}
|
||||
@@ -75,17 +70,12 @@ for (const mem of results.results) {
|
||||
| Parameter | Type | Description |
|
||||
|-----------|------|-------------|
|
||||
| `query` | string | Natural language search query |
|
||||
| `options.user_id` | string | Filter by user |
|
||||
| `options.agent_id` | string | Filter by agent |
|
||||
| `options.filters` | object | V2 filter object (`AND`/`OR`/`NOT`) |
|
||||
| `options.top_k` | number | Number of results (default: 10) |
|
||||
| `options.rerank` | boolean | Enable semantic reranking |
|
||||
| `options.threshold` | number | Minimum similarity (default: 0.3) |
|
||||
| `options.keyword_search` | boolean | Enable keyword search |
|
||||
| `options.enable_graph` | boolean | Include graph relations |
|
||||
| `options.filter_memories` | boolean | Precision filtering |
|
||||
| `options.filters` | object | Filter object with entity IDs (`user_id`, `agent_id`, etc.) and/or `AND`/`OR`/`NOT` conditions |
|
||||
| `options.topK` | number | Number of results (default: 20) |
|
||||
| `options.rerank` | boolean | Enable semantic reranking (default: false) |
|
||||
| `options.threshold` | number | Minimum similarity (default: 0.1) |
|
||||
|
||||
**Returns:** `Promise<SearchResult>` -- `{results: [{id, memory, score, ...}], relations: [...]}`
|
||||
**Returns:** `Promise<SearchResult>` -- `{results: [{id, memory, score, ...}]}`
|
||||
|
||||
#### get(memoryId)
|
||||
|
||||
@@ -98,7 +88,7 @@ const memory = await client.get('ea925981-...');
|
||||
Retrieve all memories. Requires at least one entity identifier in filters.
|
||||
|
||||
```typescript
|
||||
const memories = await client.getAll({ user_id: 'alice' });
|
||||
const memories = await client.getAll({ filters: { user_id: 'alice' } });
|
||||
// With filters
|
||||
const filtered = await client.getAll({
|
||||
filters: { AND: [{ user_id: 'alice' }, { categories: { contains: 'health' } }] },
|
||||
@@ -107,11 +97,9 @@ const filtered = await client.getAll({
|
||||
|
||||
| Parameter | Type | Description |
|
||||
|-----------|------|-------------|
|
||||
| `options.user_id` | string | Filter by user |
|
||||
| `options.filters` | object | V2 filter object |
|
||||
| `options.filters` | object | Filter object with entity IDs (`user_id`, `agent_id`, etc.) and/or `AND`/`OR`/`NOT` conditions |
|
||||
| `options.page` | number | Page number |
|
||||
| `options.page_size` | number | Results per page |
|
||||
| `options.enable_graph` | boolean | Include graph relations |
|
||||
| `options.pageSize` | number | Results per page |
|
||||
|
||||
#### update(memoryId, data)
|
||||
|
||||
@@ -136,14 +124,14 @@ await client.delete('ea925981-...');
|
||||
#### deleteAll(options?)
|
||||
|
||||
```typescript
|
||||
await client.deleteAll({ user_id: 'alice' });
|
||||
await client.deleteAll({ userId: 'alice' });
|
||||
```
|
||||
|
||||
#### history(memoryId)
|
||||
|
||||
```typescript
|
||||
const history = await client.history('ea925981-...');
|
||||
// Returns: [{previous_value, new_value, action, timestamps}]
|
||||
// Returns: [{previousValue, newValue, action, timestamps}]
|
||||
```
|
||||
|
||||
---
|
||||
@@ -179,8 +167,8 @@ const users = await client.users();
|
||||
#### deleteUser(data) / deleteUsers(data)
|
||||
|
||||
```typescript
|
||||
await client.deleteUser({ user_id: 'alice' }); // Single entity
|
||||
await client.deleteUsers({ agent_id: 'bot-1' }); // Flexible
|
||||
await client.deleteUser({ userId: 'alice' }); // Single entity
|
||||
await client.deleteUsers({ agentId: 'bot-1' }); // Flexible
|
||||
```
|
||||
|
||||
---
|
||||
@@ -189,13 +177,12 @@ await client.deleteUsers({ agent_id: 'bot-1' }); // Flexible
|
||||
|
||||
```typescript
|
||||
// Get project config
|
||||
const config = await client.getProject({ fields: ['custom_categories'] });
|
||||
const config = await client.getProject({ fields: ['customCategories'] });
|
||||
|
||||
// Update project settings
|
||||
await client.updateProject({
|
||||
custom_instructions: 'Extract dietary preferences and health info',
|
||||
custom_categories: [{ health: 'Medical and dietary info' }],
|
||||
enable_graph: true,
|
||||
customInstructions: 'Extract dietary preferences and health info',
|
||||
customCategories: [{ health: 'Medical and dietary info' }],
|
||||
});
|
||||
```
|
||||
|
||||
@@ -205,25 +192,25 @@ await client.updateProject({
|
||||
|
||||
```typescript
|
||||
// List
|
||||
const webhooks = await client.getWebhooks({ project_id: 'proj_123' });
|
||||
const webhooks = await client.getWebhooks({ projectId: 'proj_123' });
|
||||
|
||||
// Create
|
||||
const webhook = await client.createWebhook({
|
||||
url: 'https://your-app.com/webhook',
|
||||
name: 'Memory Logger',
|
||||
project_id: 'proj_123',
|
||||
event_types: ['memory_add', 'memory_update'],
|
||||
projectId: 'proj_123',
|
||||
eventTypes: ['memory_add', 'memory_update'],
|
||||
});
|
||||
|
||||
// Update
|
||||
await client.updateWebhook({
|
||||
webhook_id: 'wh_123',
|
||||
webhookId: 'wh_123',
|
||||
name: 'Updated Logger',
|
||||
url: 'https://new-url.com',
|
||||
});
|
||||
|
||||
// Delete
|
||||
await client.deleteWebhook({ webhook_id: 'wh_123' });
|
||||
await client.deleteWebhook({ webhookId: 'wh_123' });
|
||||
```
|
||||
|
||||
---
|
||||
@@ -232,9 +219,9 @@ await client.deleteWebhook({ webhook_id: 'wh_123' });
|
||||
|
||||
```typescript
|
||||
await client.feedback({
|
||||
memory_id: 'mem-123',
|
||||
memoryId: 'mem-123',
|
||||
feedback: 'POSITIVE',
|
||||
feedback_reason: 'Accurately captured preference',
|
||||
feedbackReason: 'Accurately captured preference',
|
||||
});
|
||||
```
|
||||
|
||||
@@ -248,7 +235,7 @@ const exportReq = await client.createMemoryExport({
|
||||
filters: { user_id: 'alice' },
|
||||
});
|
||||
|
||||
const result = await client.getMemoryExport({ memory_export_id: exportReq.id });
|
||||
const result = await client.getMemoryExport({ memoryExportId: exportReq.id });
|
||||
```
|
||||
|
||||
---
|
||||
@@ -259,14 +246,12 @@ Key interfaces from `mem0.types.ts`:
|
||||
|
||||
```typescript
|
||||
interface Message { role: string; content: string; }
|
||||
interface Memory { id: string; memory: string; user_id: string; categories: string[]; score?: number; /* ... */ }
|
||||
interface MemoryOptions { user_id?: string; agent_id?: string; app_id?: string; run_id?: string; metadata?: object; /* ... */ }
|
||||
interface SearchOptions { user_id?: string; filters?: object; top_k?: number; rerank?: boolean; threshold?: number; /* ... */ }
|
||||
interface MemoryHistory { id: string; memory_id: string; previous_value: string; new_value: string; action: string; /* ... */ }
|
||||
interface FeedbackPayload { memory_id: string; feedback: string; feedback_reason?: string; }
|
||||
interface WebhookCreatePayload { url: string; name: string; project_id: string; event_types: string[]; }
|
||||
enum OutputFormat { v1_0 = 'v1.0', v1_1 = 'v1.1' }
|
||||
enum API_VERSION { v1 = 'v1', v2 = 'v2' }
|
||||
interface Memory { id: string; memory: string; userId: string; categories: string[]; score?: number; /* ... */ }
|
||||
interface MemoryOptions { userId?: string; agentId?: string; appId?: string; runId?: string; metadata?: object; /* ... */ }
|
||||
interface SearchOptions { filters?: object; topK?: number; rerank?: boolean; threshold?: number; /* ... */ }
|
||||
interface MemoryHistory { id: string; memoryId: string; previousValue: string; newValue: string; action: string; /* ... */ }
|
||||
interface FeedbackPayload { memoryId: string; feedback: string; feedbackReason?: string; }
|
||||
interface WebhookCreatePayload { url: string; name: string; projectId: string; eventTypes: string[]; }
|
||||
```
|
||||
|
||||
---
|
||||
@@ -296,7 +281,7 @@ const config = {
|
||||
llm: {
|
||||
provider: 'openai', // openai, groq, anthropic, google, ollama, lmstudio, mistral, azure
|
||||
config: {
|
||||
model: 'gpt-4o-mini',
|
||||
model: 'gpt-5-mini',
|
||||
apiKey: 'sk-xxx',
|
||||
},
|
||||
},
|
||||
@@ -315,17 +300,8 @@ const config = {
|
||||
port: 6333,
|
||||
},
|
||||
},
|
||||
graphStore: { // Optional
|
||||
provider: 'neo4j',
|
||||
config: {
|
||||
url: 'neo4j://localhost:7687',
|
||||
username: 'neo4j',
|
||||
password: 'password',
|
||||
},
|
||||
},
|
||||
historyDbPath: 'history.db',
|
||||
customPrompt: '...',
|
||||
enableGraph: false,
|
||||
customInstructions: '...',
|
||||
disableHistory: false,
|
||||
};
|
||||
|
||||
@@ -363,17 +339,14 @@ await m.add([
|
||||
#### search(query, config)
|
||||
|
||||
```typescript
|
||||
const results = await m.search('dietary preferences', { userId: 'alice', limit: 5 });
|
||||
const results = await m.search('dietary preferences', { filters: { user_id: 'alice' }, topK: 5 });
|
||||
```
|
||||
|
||||
| Parameter | Type | Description |
|
||||
|-----------|------|-------------|
|
||||
| `query` | string | Search query |
|
||||
| `config.userId` | string | Filter by user |
|
||||
| `config.agentId` | string | Filter by agent |
|
||||
| `config.runId` | string | Filter by run |
|
||||
| `config.limit` | number | Max results (default: 100) |
|
||||
| `config.filters` | object | Advanced filters |
|
||||
| `config.filters` | object | Filter object with entity IDs (`user_id`, `agent_id`, `run_id`, etc.) |
|
||||
| `config.topK` | number | Max results (default: 20) |
|
||||
|
||||
#### get(memoryId) / getAll(config) / update(memoryId, data) / delete(memoryId) / deleteAll(config) / history(memoryId)
|
||||
|
||||
@@ -401,12 +374,45 @@ await m.reset();
|
||||
| **Auth** | API key required (`MEM0_API_KEY`) | No API key -- config-based |
|
||||
| **Execution** | API calls to `api.mem0.ai` | Local execution |
|
||||
| **Infrastructure** | Fully managed | Self-managed vector DB, embedder, LLM |
|
||||
| **Param style** | `snake_case` in options (`user_id`) | `camelCase` in config (`userId`) |
|
||||
| **Param style** | Top-level: `camelCase` (`userId`, `topK`), filter keys: `snake_case` (`user_id`) | Top-level: `camelCase` (`userId`, `topK`), filter keys: `snake_case` (`user_id`) |
|
||||
| **Batch ops** | `batchUpdate`, `batchDelete` | Not available |
|
||||
| **Webhooks** | Full CRUD | Not available |
|
||||
| **Export** | `createMemoryExport` | Not available |
|
||||
| **Feedback** | `feedback()` | Not available |
|
||||
| **Project mgmt** | `getProject`, `updateProject` | Not available |
|
||||
| **User listing** | `users()`, `deleteUser()` | Not available |
|
||||
| **Graph store** | Platform-managed | Self-managed (Neo4j) |
|
||||
| **History** | Platform-managed | SQLite (configurable) |
|
||||
|
||||
---
|
||||
|
||||
## v2 Compatibility
|
||||
|
||||
If you're using SDK v2.x:
|
||||
|
||||
**Naming Changes:**
|
||||
- Top-level params now use camelCase: `topK`, `rerank` (not `top_k`)
|
||||
- Filter keys use snake_case: `user_id`, `agent_id`
|
||||
- OSS: `limit` renamed to `topK`
|
||||
|
||||
**API Changes:**
|
||||
```typescript
|
||||
// v2 - top-level entity IDs, snake_case
|
||||
await client.search("query", { user_id: "alice", top_k: 20 });
|
||||
|
||||
// v3 - filters object with snake_case keys, camelCase top-level params
|
||||
await client.search("query", { filters: { user_id: "alice" }, topK: 20 });
|
||||
```
|
||||
|
||||
**Default Changes:**
|
||||
| Param | v2 | v3 |
|
||||
|-------|----|----|
|
||||
| `topK` | 100 | 20 |
|
||||
| `threshold` | none | 0.1 |
|
||||
| `rerank` | true | false |
|
||||
|
||||
**Removed:**
|
||||
- `OutputFormat` and `API_VERSION` enums
|
||||
- `organizationId`, `projectId` from constructor
|
||||
- `enableGraph`, `asyncMode`, `outputFormat`, `immutable`, `expirationDate`, `filterMemories`, `batchSize`, `forceAddOnly`, `includes`, `excludes`, `keywordSearch`
|
||||
|
||||
See the [v2 to v3 migration guide](https://docs.mem0.ai/migration/oss-v2-to-v3) for details.
|
||||
|
||||
@@ -36,7 +36,7 @@ client = AsyncMemoryClient(api_key="m0-xxx")
|
||||
|
||||
# Or use as context manager
|
||||
async with AsyncMemoryClient(api_key="m0-xxx") as client:
|
||||
results = await client.search("query", user_id="alice")
|
||||
results = await client.search("query", filters={"user_id": "alice"})
|
||||
```
|
||||
|
||||
Same methods as `MemoryClient`, all `async`/`await`. Supports async context manager.
|
||||
@@ -65,25 +65,19 @@ client.add(messages, user_id="alice")
|
||||
| `app_id` | str | None | Application identifier |
|
||||
| `run_id` | str | None | Session/run identifier |
|
||||
| `metadata` | dict | None | Custom key-value pairs |
|
||||
| `enable_graph` | bool | None | Activate knowledge graph extraction |
|
||||
| `infer` | bool | True | If False, store raw text without LLM inference |
|
||||
| `immutable` | bool | None | If True, prevents future modification |
|
||||
| `expiration_date` | str | None | Auto-expiry date (`YYYY-MM-DD`) |
|
||||
| `includes` | str | None | Preference filter for inclusion |
|
||||
| `excludes` | str | None | Preference filter for exclusion |
|
||||
| `async_mode` | bool | True | If False, wait for processing to complete |
|
||||
| `custom_categories` | list | None | Override project categories |
|
||||
| `custom_instructions` | str | None | Override extraction instructions |
|
||||
| `timestamp` | int \| float \| str | None | Custom timestamp (Unix epoch or ISO 8601) |
|
||||
|
||||
**Returns:** `dict` -- list of events: `[{"id": "...", "event": "ADD|UPDATE|DELETE", "data": {"memory": "..."}}]`
|
||||
**Returns:** `dict` -- list of events: `[{"id": "...", "event": "ADD", "data": {"memory": "..."}}]`
|
||||
|
||||
#### search(query, **kwargs)
|
||||
|
||||
Search memories by semantic similarity.
|
||||
|
||||
```python
|
||||
results = client.search("dietary preferences", user_id="alice")
|
||||
results = client.search("dietary preferences", filters={"user_id": "alice"})
|
||||
for mem in results.get("results", []):
|
||||
print(mem["memory"], mem["score"])
|
||||
```
|
||||
@@ -91,20 +85,14 @@ for mem in results.get("results", []):
|
||||
| Parameter | Type | Default | Description |
|
||||
|-----------|------|---------|-------------|
|
||||
| `query` | str | required | Natural language search query |
|
||||
| `user_id` | str | None | Filter by user |
|
||||
| `agent_id` | str | None | Filter by agent |
|
||||
| `app_id` | str | None | Filter by app |
|
||||
| `filters` | dict | None | Filter object with entity IDs and/or `AND`/`OR`/`NOT` conditions (e.g., `{"user_id": "alice"}`) |
|
||||
| `top_k` | int | 10 | Number of results |
|
||||
| `filters` | dict | None | V2 filter object (`AND`/`OR`/`NOT`) |
|
||||
| `rerank` | bool | None | Enable deep semantic reranking (+150-200ms) |
|
||||
| `threshold` | float | 0.3 | Minimum similarity score |
|
||||
| `keyword_search` | bool | None | Enable keyword-based search (+10ms) |
|
||||
| `enable_graph` | bool | None | Include graph relations in results |
|
||||
| `filter_memories` | bool | None | Precision filtering, removes low-relevance (+200-300ms) |
|
||||
| `rerank` | bool | False | Enable deep semantic reranking (+150-200ms) |
|
||||
| `threshold` | float | 0.1 | Minimum similarity score |
|
||||
| `fields` | list | None | Specific fields to return |
|
||||
| `categories` | list | None | Filter by category |
|
||||
|
||||
**Returns:** `dict` -- `{"results": [{id, memory, user_id, categories, score, created_at, ...}], "relations": [...]}`
|
||||
**Returns:** `dict` -- `{"results": [{id, memory, user_id, categories, score, created_at, ...}]}`
|
||||
|
||||
#### get(memory_id)
|
||||
|
||||
@@ -121,27 +109,23 @@ memory = client.get(memory_id="ea925981-...")
|
||||
Retrieve all memories with optional filtering. Requires at least one entity identifier.
|
||||
|
||||
```python
|
||||
memories = client.get_all(user_id="alice")
|
||||
# With filters
|
||||
memories = client.get_all(filters={"user_id": "alice"})
|
||||
# With compound filters
|
||||
memories = client.get_all(filters={"AND": [{"user_id": "alice"}, {"categories": {"contains": "health"}}]})
|
||||
```
|
||||
|
||||
| Parameter | Type | Default | Description |
|
||||
|-----------|------|---------|-------------|
|
||||
| `user_id` | str | None | Filter by user |
|
||||
| `agent_id` | str | None | Filter by agent |
|
||||
| `app_id` | str | None | Filter by app |
|
||||
| `filters` | dict | None | Filter object with entity IDs and/or `AND`/`OR`/`NOT` conditions |
|
||||
| `top_k` | int | None | Limit results |
|
||||
| `page` | int | None | Page number |
|
||||
| `page_size` | int | None | Results per page |
|
||||
| `filters` | dict | None | V2 filter object |
|
||||
| `enable_graph` | bool | None | Include graph relations |
|
||||
|
||||
**Returns:** `dict` -- `{"results": [...]}`
|
||||
|
||||
#### update(memory_id, text=None, metadata=None, timestamp=None)
|
||||
|
||||
Update a memory's content, metadata, or timestamp. At least one parameter required. Cannot update immutable memories.
|
||||
Update a memory's content, metadata, or timestamp. At least one parameter required.
|
||||
|
||||
```python
|
||||
client.update("ea925981-...", text="Updated: vegan since 2024")
|
||||
@@ -320,11 +304,10 @@ config = client.project.get(fields=["custom_categories", "custom_instructions"])
|
||||
client.project.update(
|
||||
custom_instructions="Extract dietary preferences and health info",
|
||||
custom_categories=[{"health": "Medical and dietary info"}],
|
||||
enable_graph=True,
|
||||
multilingual=True,
|
||||
)
|
||||
|
||||
# Create/delete project (requires org_id)
|
||||
# Create/delete project
|
||||
client.project.create(name="My Project", description="...")
|
||||
client.project.delete()
|
||||
|
||||
@@ -362,7 +345,7 @@ config = {
|
||||
"llm": {
|
||||
"provider": "openai", # openai, groq, azure, ollama, lmstudio, google, anthropic, mistral
|
||||
"config": {
|
||||
"model": "gpt-4o-mini",
|
||||
"model": "gpt-5-mini",
|
||||
"api_key": "sk-xxx",
|
||||
}
|
||||
},
|
||||
@@ -381,18 +364,8 @@ config = {
|
||||
"port": 6333,
|
||||
}
|
||||
},
|
||||
"graph_store": { # Optional
|
||||
"provider": "neo4j",
|
||||
"config": {
|
||||
"url": "neo4j://localhost:7687",
|
||||
"username": "neo4j",
|
||||
"password": "password",
|
||||
}
|
||||
},
|
||||
"history_db_path": "history.db", # SQLite path for change history
|
||||
"custom_instructions": "...", # Custom LLM prompt for extraction
|
||||
"custom_update_memory_prompt": "...", # Custom LLM prompt for updates
|
||||
"enable_graph": False, # Enable graph memory
|
||||
"custom_instructions": "...", # Custom LLM prompt for extraction
|
||||
}
|
||||
|
||||
m = Memory.from_config(config)
|
||||
@@ -403,7 +376,7 @@ m = Memory.from_config(config)
|
||||
```python
|
||||
with Memory(config) as m:
|
||||
m.add("I prefer dark mode", user_id="alice")
|
||||
results = m.search("preferences", user_id="alice")
|
||||
results = m.search("preferences", filters={"user_id": "alice"})
|
||||
# SQLite connections released automatically
|
||||
```
|
||||
|
||||
@@ -425,12 +398,14 @@ At least one of `user_id`, `agent_id`, `run_id` required.
|
||||
|
||||
**Returns:** `{"results": [...], "relations": [...]}`
|
||||
|
||||
#### search(query, *, user_id, agent_id, run_id, limit=100, filters=None, threshold=None, rerank=True)
|
||||
#### search(query, *, filters=None, top_k=20, threshold=0.1, rerank=False)
|
||||
|
||||
```python
|
||||
results = m.search("dietary preferences", user_id="alice", limit=5)
|
||||
results = m.search("dietary preferences", filters={"user_id": "alice"}, top_k=5)
|
||||
```
|
||||
|
||||
Entity IDs (`user_id`, `agent_id`, `run_id`) must be passed inside the `filters` dict.
|
||||
|
||||
Supports filter operators: `eq`, `ne`, `in`, `nin`, `gt`, `gte`, `lt`, `lte`, `contains`, `not_contains`.
|
||||
|
||||
#### get(memory_id) / get_all(**kwargs) / update(memory_id, data, metadata=None) / delete(memory_id) / delete_all(**kwargs) / history(memory_id)
|
||||
@@ -456,7 +431,7 @@ from mem0 import AsyncMemory
|
||||
|
||||
m = AsyncMemory(config)
|
||||
await m.add("text", user_id="alice")
|
||||
results = await m.search("query", user_id="alice")
|
||||
results = await m.search("query", filters={"user_id": "alice"})
|
||||
```
|
||||
|
||||
---
|
||||
@@ -469,13 +444,44 @@ results = await m.search("query", user_id="alice")
|
||||
| **Auth** | API key required (`MEM0_API_KEY`) | No API key -- config-based |
|
||||
| **Execution** | API calls to `api.mem0.ai` | Local execution |
|
||||
| **Infrastructure** | Fully managed | Self-managed vector DB, embedder, LLM |
|
||||
| **Entity filtering** | `filters={"user_id": "..."}` | `filters={"user_id": "..."}` |
|
||||
| **Batch ops** | `batch_update`, `batch_delete` | Not available |
|
||||
| **Webhooks** | Full CRUD | Not available |
|
||||
| **Export** | `create_memory_export`, `get_memory_export` | Not available |
|
||||
| **Feedback** | `feedback()` | Not available |
|
||||
| **Project mgmt** | `client.project.*` | Not available |
|
||||
| **User listing** | `users()`, `delete_users()` | Not available |
|
||||
| **Custom prompts** | Via project settings | Direct config |
|
||||
| **Graph store** | Platform-managed | Self-managed (Neo4j) |
|
||||
| **Custom prompts** | Via project settings | Direct config (`custom_instructions`) |
|
||||
| **History** | Platform-managed | SQLite (configurable) |
|
||||
| **Async** | `AsyncMemoryClient` | `AsyncMemory` |
|
||||
|
||||
---
|
||||
|
||||
## v2 Compatibility
|
||||
|
||||
If you're using SDK v2.x or the v2 API:
|
||||
|
||||
**API Changes:**
|
||||
- **Entity IDs in search/get_all:** Pass `user_id`, `agent_id` as top-level kwargs instead of inside `filters`
|
||||
```python
|
||||
# v2
|
||||
results = client.search("query", user_id="alice")
|
||||
# v3
|
||||
results = client.search("query", filters={"user_id": "alice"})
|
||||
```
|
||||
- **add() returns:** v2 returns ADD, UPDATE, DELETE events; v3 returns ADD only
|
||||
|
||||
**Default Changes:**
|
||||
| Param | v2 | v3 |
|
||||
|-------|----|----|
|
||||
| `top_k` | 100 | 20 |
|
||||
| `threshold` | None | 0.1 |
|
||||
| `rerank` | True | False |
|
||||
|
||||
**Removed Parameters:**
|
||||
- Constructor: `org_id`, `project_id`
|
||||
- add(): `async_mode`, `output_format`, `enable_graph`, `immutable`, `expiration_date`, `filter_memories`, `batch_size`, `force_add_only`, `includes`, `excludes`, `keyword_search`
|
||||
- search()/get_all(): `enable_graph`
|
||||
- Config: `enable_graph`, `graph_store`, `custom_fact_extraction_prompt` (renamed to `custom_instructions`)
|
||||
|
||||
See the [v2 to v3 migration guide](https://docs.mem0.ai/migration/oss-v2-to-v3) for full details.
|
||||
|
||||
@@ -8,13 +8,15 @@ All endpoints require: `Authorization: Token <MEM0_API_KEY>`
|
||||
|
||||
| Operation | Method | URL |
|
||||
|-----------|--------|-----|
|
||||
| Add Memories | `POST` | `/v1/memories/` |
|
||||
| Search Memories | `POST` | `/v2/memories/search/` |
|
||||
| Get All Memories | `POST` | `/v2/memories/` |
|
||||
| Add Memories | `POST` | `/v3/memories/add/` |
|
||||
| Search Memories | `POST` | `/v3/memories/search/` |
|
||||
| Get All Memories | `POST` | `/v3/memories/` |
|
||||
| Get Single Memory | `GET` | `/v1/memories/{memory_id}/` |
|
||||
| Update Memory | `PUT` | `/v1/memories/{memory_id}/` |
|
||||
| Delete Memory | `DELETE` | `/v1/memories/{memory_id}/` |
|
||||
|
||||
Note: v1/v2 endpoints still work (backward compatible).
|
||||
|
||||
## Memory Object Structure
|
||||
|
||||
| Field | Type | Description |
|
||||
@@ -27,8 +29,6 @@ All endpoints require: `Authorization: Token <MEM0_API_KEY>`
|
||||
| `run_id` | string (nullable) | Run/session identifier |
|
||||
| `metadata` | object | Custom key-value pairs |
|
||||
| `categories` | array of strings | Auto-assigned category tags |
|
||||
| `immutable` | boolean | If true, prevents modification |
|
||||
| `expiration_date` | datetime (nullable) | Auto-expiry date |
|
||||
| `hash` | string | Content hash |
|
||||
| `created_at` | datetime | Creation timestamp |
|
||||
| `updated_at` | datetime | Last modification timestamp |
|
||||
@@ -50,10 +50,9 @@ Memories can be scoped to different levels:
|
||||
|
||||
## Processing Model
|
||||
|
||||
- Memories are processed **asynchronously by default** (`async_mode=true`)
|
||||
- Add responses return queued events (`ADD`, `UPDATE`, `DELETE`) for tracking
|
||||
- Set `async_mode=false` for synchronous processing when needed
|
||||
- Graph metadata is processed asynchronously -- use `get_all()` for complete graph data
|
||||
- Memories are processed **asynchronously** (v3 default)
|
||||
- Add responses return queued `ADD` events only (v3 is ADD-only, no UPDATE/DELETE)
|
||||
- Poll status via `GET /v1/event/{event_id}/`
|
||||
|
||||
## Filter System
|
||||
|
||||
@@ -106,19 +105,17 @@ Root must be `AND`, `OR`, or `NOT`. Simple shorthand `{"user_id": "alice"}` also
|
||||
|
||||
## Response Formats
|
||||
|
||||
### Add Response
|
||||
### Add Response (v3)
|
||||
|
||||
```json
|
||||
[
|
||||
{
|
||||
"id": "mem_01JF8ZS4Y0R0SPM13R5R6H32CJ",
|
||||
"event": "ADD",
|
||||
"data": { "memory": "The user moved to Austin in 2025." }
|
||||
}
|
||||
]
|
||||
{
|
||||
"message": "Memory processing has been queued for background execution",
|
||||
"status": "PENDING",
|
||||
"event_id": "evt-uuid"
|
||||
}
|
||||
```
|
||||
|
||||
Event types: `ADD`, `UPDATE`, `DELETE`. A single add can trigger multiple events.
|
||||
v3 is ADD-only. No UPDATE or DELETE events.
|
||||
|
||||
### Search Response
|
||||
|
||||
@@ -137,4 +134,17 @@ Event types: `ADD`, `UPDATE`, `DELETE`. A single add can trigger multiple events
|
||||
}
|
||||
```
|
||||
|
||||
With `enable_graph=true`, includes additional `relations` array with entity relationships.
|
||||
In v3, `score` is a combined multi-signal relevance score.
|
||||
|
||||
### Get All Response (v3)
|
||||
|
||||
```json
|
||||
{
|
||||
"count": 123,
|
||||
"next": "https://api.mem0.ai/v3/memories/?page=2&page_size=50",
|
||||
"previous": null,
|
||||
"results": [...]
|
||||
}
|
||||
```
|
||||
|
||||
v3 returns paginated envelope. Use `page` and `page_size` query params.
|
||||
|
||||
@@ -25,9 +25,9 @@ User Input → Retrieve relevant memories → Enrich LLM prompt → Generate res
|
||||
|
||||
Mem0 handles the complexity of extraction, deduplication, conflict resolution, and semantic retrieval so your application only needs to call `search()` and `add()`.
|
||||
|
||||
**Dual storage architecture:**
|
||||
**Storage architecture:**
|
||||
- **Vector store**: Embeddings for semantic similarity search
|
||||
- **Graph store** (optional): Entity nodes and relationship edges for structured knowledge
|
||||
- **Entity store**: Automatic entity linking for relationship-aware retrieval
|
||||
|
||||
---
|
||||
|
||||
@@ -40,41 +40,32 @@ Messages In
|
||||
│
|
||||
▼
|
||||
┌─────────────────────┐
|
||||
│ 1. EXTRACTION │ LLM analyzes messages, extracts key facts
|
||||
│ 1. EXTRACTION │ Single LLM call extracts all distinct new facts
|
||||
│ (infer=True) │ If infer=False, stores raw text as-is
|
||||
└─────────┬───────────┘
|
||||
│
|
||||
▼
|
||||
┌─────────────────────┐
|
||||
│ 2. CONFLICT │ Checks existing memories for duplicates
|
||||
│ RESOLUTION │ Latest truth wins (newer overrides older)
|
||||
│ │ Only runs when infer=True
|
||||
│ 2. DEDUPLICATION │ Hash-based dedup (MD5 prevents exact duplicates)
|
||||
│ │ No UPDATE/DELETE - v3 is ADD-only
|
||||
└─────────┬───────────┘
|
||||
│
|
||||
▼
|
||||
┌─────────────────────┐
|
||||
│ 3. STORAGE │ Generates embeddings → vector store
|
||||
│ │ Optional: entity extraction → graph store
|
||||
│ │ Indexes metadata, categories, timestamps
|
||||
│ 3. STORAGE │ Batch embed → vector store
|
||||
│ │ Entity extraction → entity store
|
||||
└─────────┬───────────┘
|
||||
│
|
||||
▼
|
||||
Memory Object
|
||||
(id, memory, categories, structured_attributes)
|
||||
```
|
||||
|
||||
### Processing modes
|
||||
### Processing (v3)
|
||||
|
||||
**Async (default, `async_mode=True`):**
|
||||
- API returns immediately: `{"status": "PENDING", "event_id": "..."}`
|
||||
- Processing happens in background
|
||||
v3 processes memories asynchronously by default:
|
||||
- API returns immediately: `{"status": "PENDING", "event_id": "evt-..."}`
|
||||
- Poll status via `GET /v1/event/{event_id}/`
|
||||
- Use webhooks for completion notifications
|
||||
- Best for: high-throughput, non-blocking workflows
|
||||
|
||||
**Sync (`async_mode=False`):**
|
||||
- API waits for full processing
|
||||
- Returns complete memory object with `id`, `event`, `memory`
|
||||
- Best for: real-time access immediately after add
|
||||
|
||||
### Extraction modes
|
||||
|
||||
@@ -93,7 +84,7 @@ Messages In
|
||||
|
||||
---
|
||||
|
||||
## Retrieval Pipeline
|
||||
## Retrieval Pipeline (v3)
|
||||
|
||||
### What happens when you call `client.search()`
|
||||
|
||||
@@ -102,45 +93,37 @@ Query In
|
||||
│
|
||||
▼
|
||||
┌─────────────────────┐
|
||||
│ 1. QUERY EMBEDDING │ Convert query to vector representation
|
||||
│ 1. PREPROCESSING │ Lemmatize keywords, extract entities
|
||||
└─────────┬───────────┘
|
||||
│
|
||||
▼
|
||||
┌─────────────────────┐
|
||||
│ 2. VECTOR SEARCH │ Cosine similarity across stored embeddings
|
||||
│ │ Scoped by filters (user_id, agent_id, etc.)
|
||||
└─────────┬───────────┘
|
||||
│
|
||||
▼ (optional enhancements)
|
||||
┌─────────────────────┐
|
||||
│ 3a. KEYWORD SEARCH │ Expands results with specific terms (+10ms)
|
||||
│ 3b. RERANKING │ Deep semantic reordering (+150-200ms)
|
||||
│ 3c. FILTER MEMORIES │ Precision filtering, removes low-relevance (+200-300ms)
|
||||
└─────────┬───────────┘
|
||||
│
|
||||
▼ (if enable_graph=True)
|
||||
┌─────────────────────┐
|
||||
│ 4. GRAPH LOOKUP │ Finds entity relationships
|
||||
│ │ Appends relations WITHOUT reranking vector results
|
||||
│ 2. PARALLEL SCORING │ Semantic search (vector similarity)
|
||||
│ │ BM25 keyword search (term matching)
|
||||
│ │ Entity matching (entity graph boost)
|
||||
└─────────┬───────────┘
|
||||
│
|
||||
▼
|
||||
Results + Relations
|
||||
┌─────────────────────┐
|
||||
│ 3. SCORE FUSION │ Combine signals into single score
|
||||
│ │ Optional: rerank=True for deep reordering
|
||||
└─────────┬───────────┘
|
||||
│
|
||||
▼
|
||||
Results (combined score per memory)
|
||||
```
|
||||
|
||||
### Retrieval enhancement combinations
|
||||
### v3 Search Defaults
|
||||
|
||||
| Configuration | Latency | Best for |
|
||||
|--------------|---------|----------|
|
||||
| Base search only | ~100ms | Simple lookups |
|
||||
| `keyword_search=True` | ~110ms | Entity-heavy queries, broad coverage |
|
||||
| `rerank=True` | ~250-300ms | User-facing results, top-N precision |
|
||||
| `keyword_search=True` + `rerank=True` | ~310ms | Balanced (recommended for most apps) |
|
||||
| `rerank=True` + `filter_memories=True` | ~400-500ms | Safety-critical, production systems |
|
||||
| Parameter | Default | Notes |
|
||||
|-----------|---------|-------|
|
||||
| `top_k` | 20 | Was 100 in v2 |
|
||||
| `threshold` | 0.1 | Was None in v2 |
|
||||
| `rerank` | False | Was True in v2 |
|
||||
|
||||
### Implicit null scoping
|
||||
|
||||
When you search with `user_id="alice"` only, Mem0 returns memories where `agent_id`, `app_id`, and `run_id` are all null. This prevents cross-scope leakage by default.
|
||||
When you search with `filters={"user_id": "alice"}` only, Mem0 returns memories where `agent_id`, `app_id`, and `run_id` are all null. This prevents cross-scope leakage by default.
|
||||
|
||||
To include memories with non-null fields, use explicit filters:
|
||||
```python
|
||||
@@ -150,53 +133,23 @@ filters={"OR": [{"user_id": "alice"}]}
|
||||
|
||||
---
|
||||
|
||||
## Memory Lifecycle
|
||||
## Memory Lifecycle (v3)
|
||||
|
||||
```
|
||||
CREATE ──→ ACTIVE ──→ UPDATE ──→ ACTIVE
|
||||
│ │ │
|
||||
│ ▼ ▼
|
||||
│ EXPIRED EXPIRED
|
||||
│ (still stored, (still stored,
|
||||
│ not retrieved) not retrieved)
|
||||
│ │ │
|
||||
▼ ▼ ▼
|
||||
DELETE DELETE DELETE
|
||||
(permanent)
|
||||
```
|
||||
v3 uses ADD-only extraction. Memories accumulate over time rather than being consolidated.
|
||||
|
||||
### Creation
|
||||
- Triggered by `client.add(messages, user_id="...")`
|
||||
- Messages processed through extraction → conflict resolution → storage
|
||||
- Gets unique UUID, `created_at` timestamp
|
||||
- Optional: custom `timestamp`, `expiration_date`, `metadata`, `immutable`
|
||||
- `client.add(messages, user_id="...")`
|
||||
- Single-pass extraction → deduplication → storage
|
||||
- Returns `{"event_id": "...", "status": "PENDING"}`
|
||||
|
||||
### Updates
|
||||
- `client.update(memory_id, text="...")` replaces text and reindexes
|
||||
- `client.batch_update([...])` for up to 1000 memories at once
|
||||
- Immutable memories (`immutable=True`) cannot be updated — must delete and re-add
|
||||
|
||||
### Deduplication
|
||||
- Automatic during `add()` with `infer=True`
|
||||
- Conflict resolution merges duplicate facts
|
||||
- Latest truth wins when contradictions detected
|
||||
- Prevents memory bloat from repeated information
|
||||
|
||||
### Expiration
|
||||
- Optional `expiration_date` parameter (ISO 8601 or `YYYY-MM-DD`)
|
||||
- After expiration: memory NOT returned in searches but remains in storage
|
||||
- Useful for time-sensitive info (events, temporary preferences, session state)
|
||||
- `client.update(memory_id, text="...")` replaces text
|
||||
- Batch: `client.batch_update([...])`
|
||||
|
||||
### Deletion
|
||||
- Single: `client.delete(memory_id)` — permanent, no recovery
|
||||
- Batch: `client.batch_delete([memory_ids])` — up to 1000
|
||||
- Bulk: `client.delete_all(user_id="alice")` — all memories for entity
|
||||
- `delete_all()` without filters raises error to prevent accidental data loss
|
||||
|
||||
### History tracking
|
||||
- `client.history(memory_id)` returns version timeline
|
||||
- Shows all changes: `{previous_value, new_value, action, timestamps}`
|
||||
- Useful for audit trails and debugging
|
||||
- Single: `client.delete(memory_id)`
|
||||
- Batch: `client.batch_delete([...])`
|
||||
- Bulk: `client.delete_all(filters={"user_id": "alice"})`
|
||||
|
||||
---
|
||||
|
||||
@@ -214,8 +167,6 @@ DELETE DELETE DELETE
|
||||
"categories": ["health", "preferences"],
|
||||
"created_at": "2025-03-12T12:34:56Z",
|
||||
"updated_at": "2025-03-12T12:34:56Z",
|
||||
"expiration_date": null,
|
||||
"immutable": false,
|
||||
"structured_attributes": {
|
||||
"day": 12, "month": 3, "year": 2025,
|
||||
"hour": 12, "minute": 34,
|
||||
@@ -239,8 +190,6 @@ DELETE DELETE DELETE
|
||||
| `categories` | array | Auto-assigned or custom category tags |
|
||||
| `created_at` | datetime | Creation timestamp |
|
||||
| `updated_at` | datetime | Last modification timestamp |
|
||||
| `expiration_date` | datetime | Auto-expiry date (stops retrieval, data persists) |
|
||||
| `immutable` | boolean | If true, prevents modification |
|
||||
| `structured_attributes` | object | Temporal breakdown for time-based queries |
|
||||
| `score` | float | Semantic similarity (search results only, 0-1) |
|
||||
|
||||
@@ -322,7 +271,7 @@ Mem0 supports three layers of memory, from shortest to longest lived:
|
||||
```python
|
||||
def chat(user_input: str, user_id: str, session_id: str) -> str:
|
||||
# 1. Retrieve user memories (long-term preferences)
|
||||
user_mems = mem0.search(user_input, user_id=user_id)
|
||||
user_mems = mem0.search(user_input, filters={"user_id": user_id})
|
||||
|
||||
# 2. Retrieve session memories (current task context)
|
||||
session_mems = mem0.search(user_input, filters={
|
||||
@@ -350,18 +299,13 @@ def chat(user_input: str, user_id: str, session_id: str) -> str:
|
||||
|
||||
| Operation | Typical Latency |
|
||||
|-----------|----------------|
|
||||
| Base vector search | ~100ms |
|
||||
| + keyword_search | +10ms |
|
||||
| Hybrid search (v3 default) | ~100-150ms |
|
||||
| + reranking | +150-200ms |
|
||||
| + filter_memories | +200-300ms |
|
||||
| Add (async, default) | < 50ms response, background processing |
|
||||
| Add (sync) | 500ms-2s depending on extraction complexity |
|
||||
| Graph operations | Slight overhead for large stores |
|
||||
| Add (async) | < 50ms response |
|
||||
|
||||
### Processing
|
||||
|
||||
- **Async mode (default):** Returns immediately, processes in background
|
||||
- **Sync mode:** Waits for full extraction + storage pipeline
|
||||
- **Async (default):** Returns immediately, processes in background
|
||||
- **Batch operations:** Up to 1000 memories per batch_update/batch_delete
|
||||
- **Webhooks:** Real-time notifications when async processing completes
|
||||
|
||||
|
||||
@@ -5,7 +5,7 @@ Additional platform capabilities beyond core CRUD operations.
|
||||
## Table of Contents
|
||||
|
||||
- [Advanced Retrieval](#advanced-retrieval)
|
||||
- [Graph Memory](#graph-memory)
|
||||
- [Entity Linking](#entity-linking)
|
||||
- [Custom Categories](#custom-categories)
|
||||
- [Custom Instructions](#custom-instructions)
|
||||
- [Criteria Retrieval](#criteria-retrieval)
|
||||
@@ -18,124 +18,58 @@ Additional platform capabilities beyond core CRUD operations.
|
||||
|
||||
## Advanced Retrieval
|
||||
|
||||
Three enhancement options for tuning search precision, recall, and latency.
|
||||
### Hybrid Search (v3 Default)
|
||||
|
||||
### Keyword Search (`keyword_search=True`)
|
||||
v3 uses multi-signal hybrid search combining:
|
||||
- **Semantic search** (vector similarity)
|
||||
- **BM25 keyword search** (normalized term matching)
|
||||
- **Entity matching** (entity graph boost)
|
||||
|
||||
Expands results to include memories with specific terms, names, and technical keywords.
|
||||
|
||||
- Latency: +10ms
|
||||
- Recall: Significantly increased
|
||||
- Best for: entity-heavy queries, comprehensive coverage
|
||||
This is automatic — no configuration needed.
|
||||
|
||||
### Reranking (`rerank=True`)
|
||||
|
||||
Deep semantic reordering of results — most relevant first.
|
||||
|
||||
- Latency: +150-200ms
|
||||
- Accuracy: Significantly improved
|
||||
- Default: `False` (was `True` in v2)
|
||||
- Best for: user-facing results, top-N precision
|
||||
|
||||
### Filter Memories (`filter_memories=True`)
|
||||
|
||||
Precision filtering — removes low-relevance results entirely.
|
||||
|
||||
- Latency: +200-300ms
|
||||
- Precision: Maximized
|
||||
- Best for: safety-critical applications, production systems
|
||||
|
||||
### Recommended Combinations
|
||||
|
||||
**Python:**
|
||||
```python
|
||||
# Fast & broad
|
||||
results = client.search(query, keyword_search=True, user_id="user123")
|
||||
|
||||
# Balanced (recommended for most apps)
|
||||
results = client.search(query, keyword_search=True, rerank=True, user_id="user123")
|
||||
|
||||
# High precision (critical apps)
|
||||
results = client.search(query, rerank=True, filter_memories=True, user_id="user123")
|
||||
results = client.search(query, filters={"user_id": "user123"}, rerank=True)
|
||||
```
|
||||
|
||||
**TypeScript:**
|
||||
```typescript
|
||||
const results = await client.search(query, {
|
||||
user_id: 'user123',
|
||||
keyword_search: true,
|
||||
filters: { user_id: 'user123' },
|
||||
rerank: true,
|
||||
});
|
||||
```
|
||||
|
||||
---
|
||||
|
||||
## Graph Memory
|
||||
## Entity Linking
|
||||
|
||||
Entity-level knowledge graph that creates relationships between memories.
|
||||
v3 replaces graph memory with built-in entity linking. Entities (proper nouns, quoted text, compound noun phrases) are automatically extracted and linked across memories.
|
||||
|
||||
### How It Works
|
||||
|
||||
1. **Extraction**: LLM analyzes conversation and identifies entities and relationships
|
||||
2. **Storage**: Embeddings go to vector store; entity nodes and edges go to graph store
|
||||
3. **Retrieval**: Vector search returns semantic matches; graph relations are appended to results
|
||||
1. **Extraction**: During `add()`, entities are automatically extracted from memory text
|
||||
2. **Storage**: Entities are stored in a parallel collection (`{collection}_entities`)
|
||||
3. **Retrieval**: During `search()`, query entities are matched and used to boost relevant memories
|
||||
|
||||
Graph relations **augment** vector results without reordering them. Vector similarity always determines hit sequence.
|
||||
Entity linking is automatic — no configuration required. The boost is folded into the combined `score` on each result.
|
||||
|
||||
### Enabling Graph Memory
|
||||
### v2 Migration Note
|
||||
|
||||
**Per request:**
|
||||
```python
|
||||
client.add(messages, user_id="alice", enable_graph=True)
|
||||
client.search("query", user_id="alice", enable_graph=True)
|
||||
client.get_all(filters={"AND": [{"user_id": "alice"}]}, enable_graph=True)
|
||||
```
|
||||
If you were using `enable_graph=True` in v2:
|
||||
- Remove `enable_graph` from all API calls
|
||||
- Remove `graph_store` from OSS configuration
|
||||
- Entity relationships are now consumed through retrieval ranking, not exposed as a separate `relations` array
|
||||
|
||||
**Project-level (default for all operations):**
|
||||
```python
|
||||
client.project.update(enable_graph=True)
|
||||
```
|
||||
|
||||
```javascript
|
||||
await client.updateProject({ enable_graph: true });
|
||||
```
|
||||
|
||||
### Relation Structure
|
||||
|
||||
Each relation in the response contains:
|
||||
|
||||
| Field | Type | Description |
|
||||
|-------|------|-------------|
|
||||
| `source` | string | Source entity name |
|
||||
| `source_type` | string | Source entity type (e.g., "Person") |
|
||||
| `relationship` | string | Relationship label (e.g., "lives_in") |
|
||||
| `target` | string | Target entity name |
|
||||
| `target_type` | string | Target entity type (e.g., "City") |
|
||||
| `score` | number | Confidence score |
|
||||
|
||||
**Example:**
|
||||
```json
|
||||
{
|
||||
"relations": [
|
||||
{
|
||||
"source": "Joseph",
|
||||
"source_type": "Person",
|
||||
"relationship": "lives_in",
|
||||
"target": "Seattle",
|
||||
"target_type": "City",
|
||||
"score": 0.92
|
||||
}
|
||||
]
|
||||
}
|
||||
```
|
||||
|
||||
### Technical Notes
|
||||
|
||||
- Graph Memory adds processing time; see docs for current plan availability
|
||||
- Works optimally with rich conversation histories containing entity relationships
|
||||
- Best suited for long-running assistants tracking evolving information
|
||||
- Graph writes and reads toggle independently per request
|
||||
- Multi-agent context supported via `user_id`, `agent_id`, `run_id` scoping
|
||||
- Add operations are asynchronous; graph metadata may not be immediately available
|
||||
See the [v2 to v3 migration guide](https://docs.mem0.ai/migration/oss-v2-to-v3) for details.
|
||||
|
||||
---
|
||||
|
||||
@@ -160,7 +94,7 @@ client.project.update(custom_categories=new_categories)
|
||||
```
|
||||
|
||||
```javascript
|
||||
await client.updateProject({ custom_categories: new_categories });
|
||||
await client.updateProject({ customCategories: newCategories });
|
||||
```
|
||||
|
||||
**Retrieve active categories:**
|
||||
@@ -185,7 +119,7 @@ client.project.update(custom_instructions="Your guidelines here...")
|
||||
```
|
||||
|
||||
```javascript
|
||||
await client.updateProject({ custom_instructions: "Your guidelines here..." });
|
||||
await client.updateProject({ customInstructions: "Your guidelines here..." });
|
||||
```
|
||||
|
||||
### Template Structure
|
||||
@@ -229,7 +163,7 @@ client.project.update(retrieval_criteria=retrieval_criteria)
|
||||
|
||||
```typescript
|
||||
await client.updateProject({
|
||||
retrieval_criteria: [
|
||||
retrievalCriteria: [
|
||||
{ name: 'joy', description: 'Positive emotions', weight: 3 },
|
||||
{ name: 'urgency', description: 'Time-sensitive items', weight: 4 },
|
||||
],
|
||||
@@ -281,7 +215,7 @@ for item in feedback_data:
|
||||
```typescript
|
||||
await client.feedback('mem-123', {
|
||||
feedback: 'POSITIVE',
|
||||
feedback_reason: 'Accurately captured dietary preference',
|
||||
feedbackReason: 'Accurately captured dietary preference',
|
||||
});
|
||||
```
|
||||
|
||||
|
||||
@@ -27,7 +27,7 @@ from langchain_core.messages import SystemMessage, HumanMessage
|
||||
from langchain_core.prompts import ChatPromptTemplate, MessagesPlaceholder
|
||||
from mem0 import MemoryClient
|
||||
|
||||
llm = ChatOpenAI(model="gpt-4.1-nano-2025-04-14")
|
||||
llm = ChatOpenAI(model="gpt-5-mini")
|
||||
mem0 = MemoryClient()
|
||||
|
||||
prompt = ChatPromptTemplate.from_messages([
|
||||
@@ -128,7 +128,7 @@ import { createMem0 } from "@mem0/vercel-ai-provider";
|
||||
|
||||
const mem0 = createMem0();
|
||||
const { text } = await generateText({
|
||||
model: mem0("gpt-4-turbo", { user_id: "borat" }),
|
||||
model: mem0("gpt-5-mini", { user_id: "borat" }),
|
||||
prompt: "Suggest me a good car to buy!",
|
||||
});
|
||||
```
|
||||
@@ -167,7 +167,7 @@ agent = Agent(
|
||||
Use search_memory to recall past conversations.
|
||||
Use save_memory to store important information.""",
|
||||
tools=[search_memory, save_memory],
|
||||
model="gpt-4.1-nano-2025-04-14"
|
||||
model="gpt-5-mini"
|
||||
)
|
||||
|
||||
result = Runner.run_sync(agent, "I love Italian food and I'm planning a trip to Rome next month")
|
||||
@@ -183,21 +183,21 @@ travel_agent = Agent(
|
||||
name="Travel Planner",
|
||||
instructions="You are a travel planning specialist. Use search_memory and save_memory tools.",
|
||||
tools=[search_memory, save_memory],
|
||||
model="gpt-4.1-nano-2025-04-14"
|
||||
model="gpt-5-mini"
|
||||
)
|
||||
|
||||
health_agent = Agent(
|
||||
name="Health Advisor",
|
||||
instructions="You are a health and wellness advisor. Use search_memory and save_memory tools.",
|
||||
tools=[search_memory, save_memory],
|
||||
model="gpt-4.1-nano-2025-04-14"
|
||||
model="gpt-5-mini"
|
||||
)
|
||||
|
||||
triage_agent = Agent(
|
||||
name="Personal Assistant",
|
||||
instructions="""Route travel questions to Travel Planner, health questions to Health Advisor.""",
|
||||
handoffs=[travel_agent, health_agent],
|
||||
model="gpt-4.1-nano-2025-04-14"
|
||||
model="gpt-5-mini"
|
||||
)
|
||||
|
||||
result = Runner.run_sync(triage_agent, "Plan a healthy meal for my Italy trip")
|
||||
@@ -254,7 +254,7 @@ from langchain_openai import ChatOpenAI
|
||||
from mem0 import MemoryClient
|
||||
from langchain_core.messages import SystemMessage, HumanMessage, AIMessage
|
||||
|
||||
llm = ChatOpenAI(model="gpt-4")
|
||||
llm = ChatOpenAI(model="gpt-5-mini")
|
||||
mem0 = MemoryClient()
|
||||
|
||||
class State(TypedDict):
|
||||
@@ -319,7 +319,7 @@ memory = Mem0Memory.from_client(
|
||||
from llama_index.core.agent import FunctionCallingAgent
|
||||
from llama_index.llms.openai import OpenAI
|
||||
|
||||
llm = OpenAI(model="gpt-4")
|
||||
llm = OpenAI(model="gpt-5-mini")
|
||||
agent = FunctionCallingAgent.from_tools(
|
||||
tools=[],
|
||||
llm=llm,
|
||||
@@ -352,7 +352,7 @@ USER_ID = "alice"
|
||||
|
||||
agent = ConversableAgent(
|
||||
"chatbot",
|
||||
llm_config={"config_list": [{"model": "gpt-4", "api_key": os.environ["OPENAI_API_KEY"]}]},
|
||||
llm_config={"config_list": [{"model": "gpt-5-mini", "api_key": os.environ["OPENAI_API_KEY"]}]},
|
||||
code_execution_config=False,
|
||||
human_input_mode="NEVER",
|
||||
)
|
||||
|
||||
@@ -59,11 +59,11 @@ const messages = [
|
||||
{"role": "user", "content": "I'm a vegetarian and allergic to nuts."},
|
||||
{"role": "assistant", "content": "Got it! I'll remember your dietary preferences."}
|
||||
];
|
||||
await client.add(messages, { user_id: "user123" });
|
||||
await client.add(messages, { userId: "user123" });
|
||||
|
||||
// Search memories
|
||||
const results = await client.search("What are my dietary restrictions?", {
|
||||
user_id: "user123"
|
||||
filters: { user_id: "user123" }
|
||||
});
|
||||
console.log(results);
|
||||
```
|
||||
|
||||
@@ -40,16 +40,12 @@ client.add(messages, user_id="alice")
|
||||
|
||||
# With metadata
|
||||
client.add(messages, user_id="alice", metadata={"source": "onboarding"})
|
||||
|
||||
# With graph memory
|
||||
client.add(messages, user_id="alice", enable_graph=True)
|
||||
```
|
||||
|
||||
**TypeScript:**
|
||||
```typescript
|
||||
await client.add(messages, { user_id: "alice" });
|
||||
await client.add(messages, { user_id: "alice", metadata: { source: "onboarding" } });
|
||||
await client.add(messages, { user_id: "alice", enable_graph: true });
|
||||
await client.add(messages, { userId: "alice" });
|
||||
await client.add(messages, { userId: "alice", metadata: { source: "onboarding" } });
|
||||
```
|
||||
|
||||
### Parameters
|
||||
@@ -61,32 +57,14 @@ await client.add(messages, { user_id: "alice", enable_graph: true });
|
||||
| `agent_id` | string | Agent identifier |
|
||||
| `run_id` | string | Session identifier |
|
||||
| `metadata` | object | Custom key-value pairs |
|
||||
| `enable_graph` | boolean | Activate knowledge graph |
|
||||
| `infer` | boolean | If `false`, store raw text without inference (default: `true`) |
|
||||
| `immutable` | boolean | Prevents modification after creation |
|
||||
| `expiration_date` | string | Auto-expiry date (`YYYY-MM-DD`) |
|
||||
| `includes` | string | Preference filters for inclusion |
|
||||
| `excludes` | string | Preference filters for exclusion |
|
||||
| `async_mode` | boolean | Async processing (default: `true`). Set `false` to wait |
|
||||
|
||||
### Advanced Add Options
|
||||
|
||||
```python
|
||||
# Immutable -- cannot be modified or overwritten
|
||||
client.add(messages, user_id="alice", immutable=True)
|
||||
|
||||
# Expiring memory
|
||||
client.add(messages, user_id="alice", expiration_date="2025-12-31")
|
||||
|
||||
# Selective extraction
|
||||
client.add(messages, user_id="alice", includes="dietary preferences", excludes="payment info")
|
||||
|
||||
# Agent + session scoping
|
||||
client.add(messages, user_id="alice", agent_id="nutrition-agent", run_id="session-456")
|
||||
|
||||
# Synchronous processing (wait for completion)
|
||||
client.add(messages, user_id="alice", async_mode=False)
|
||||
|
||||
# Raw text -- skip LLM inference
|
||||
client.add(
|
||||
[{"role": "user", "content": "User prefers dark mode."}],
|
||||
@@ -101,7 +79,7 @@ client.add(
|
||||
|
||||
**Python:**
|
||||
```python
|
||||
results = client.search("dietary preferences?", user_id="alice")
|
||||
results = client.search("dietary preferences?", filters={"user_id": "alice"})
|
||||
|
||||
# With filters and reranking
|
||||
results = client.search(
|
||||
@@ -111,20 +89,14 @@ results = client.search(
|
||||
rerank=True,
|
||||
threshold=0.5
|
||||
)
|
||||
|
||||
# With graph relations
|
||||
results = client.search("colleagues", user_id="alice", enable_graph=True)
|
||||
|
||||
# Keyword search
|
||||
results = client.search("vegetarian", user_id="alice", keyword_search=True)
|
||||
```
|
||||
|
||||
**TypeScript:**
|
||||
```typescript
|
||||
const results = await client.search("dietary preferences", { user_id: "alice" });
|
||||
const results = await client.search("dietary preferences", { filters: { user_id: "alice" } });
|
||||
const results = await client.search("work experience", {
|
||||
filters: { AND: [{ user_id: "alice" }, { categories: { contains: "professional_details" } }] },
|
||||
top_k: 5,
|
||||
topK: 5,
|
||||
rerank: true,
|
||||
});
|
||||
```
|
||||
@@ -134,19 +106,17 @@ const results = await client.search("work experience", {
|
||||
| Name | Type | Description |
|
||||
|------|------|-------------|
|
||||
| `query` | string | Natural language search query |
|
||||
| `user_id` | string | Filter by user |
|
||||
| `filters` | object | V2 filter object (AND/OR operators) |
|
||||
| `top_k` | number | Number of results (default: 10) |
|
||||
| `rerank` | boolean | Enable reranking for better relevance |
|
||||
| `threshold` | number | Minimum similarity score (default: 0.3) |
|
||||
| `keyword_search` | boolean | Use keyword-based search |
|
||||
| `enable_graph` | boolean | Include graph relations |
|
||||
| `filters` | object | Filter object (AND/OR operators). Use `{"user_id": "..."}` to filter by user |
|
||||
| `top_k` | number | Number of results (default: 10 for Platform) |
|
||||
| `rerank` | boolean | Enable reranking for better relevance (default: `false`) |
|
||||
| `threshold` | number | Minimum similarity score (default: 0.1) |
|
||||
|
||||
### Common Filter Patterns
|
||||
|
||||
**Python:**
|
||||
```python
|
||||
# Single user (shorthand)
|
||||
client.search("query", user_id="alice")
|
||||
# Single user filter
|
||||
filters={"user_id": "alice"}
|
||||
|
||||
# OR across agents
|
||||
filters={"OR": [{"user_id": "alice"}, {"agent_id": {"in": ["travel-agent", "sports-agent"]}}]}
|
||||
@@ -179,6 +149,21 @@ filters={"AND": [
|
||||
]}
|
||||
```
|
||||
|
||||
**TypeScript:**
|
||||
```typescript
|
||||
// Single user filter
|
||||
filters: { user_id: "alice" }
|
||||
|
||||
// OR across agents
|
||||
filters: { OR: [{ user_id: "alice" }, { agent_id: { in: ["travel-agent", "sports-agent"] } }] }
|
||||
|
||||
// Category filtering (partial match)
|
||||
filters: { AND: [{ user_id: "alice" }, { categories: { contains: "finance" } }] }
|
||||
|
||||
// Category filtering (exact match)
|
||||
filters: { AND: [{ user_id: "alice" }, { categories: { in: ["personal_information"] } }] }
|
||||
```
|
||||
|
||||
---
|
||||
|
||||
## get() / getAll() -- Retrieve Memories
|
||||
@@ -189,7 +174,7 @@ filters={"AND": [
|
||||
memory = client.get(memory_id="ea925981-...")
|
||||
|
||||
# All memories for a user
|
||||
memories = client.get_all(filters={"AND": [{"user_id": "alice"}]})
|
||||
memories = client.get_all(filters={"user_id": "alice"})
|
||||
|
||||
# With date range
|
||||
memories = client.get_all(
|
||||
@@ -198,15 +183,12 @@ memories = client.get_all(
|
||||
{"created_at": {"gte": "2024-07-01", "lte": "2024-07-31"}}
|
||||
]}
|
||||
)
|
||||
|
||||
# With graph data
|
||||
memories = client.get_all(filters={"AND": [{"user_id": "alice"}]}, enable_graph=True)
|
||||
```
|
||||
|
||||
**TypeScript:**
|
||||
```typescript
|
||||
const memory = await client.get("ea925981-...");
|
||||
const memories = await client.getAll({ filters: { AND: [{ user_id: "alice" }] } });
|
||||
const memories = await client.getAll({ filters: { user_id: "alice" } });
|
||||
```
|
||||
|
||||
**Note:** `get_all` requires at least one of `user_id`, `agent_id`, `app_id`, or `run_id` in filters.
|
||||
@@ -226,8 +208,6 @@ client.update(memory_id="ea925981-...", text="Updated", metadata={"verified": Tr
|
||||
await client.update("ea925981-...", { text: "Updated: vegan since 2024" });
|
||||
```
|
||||
|
||||
Cannot update immutable memories.
|
||||
|
||||
---
|
||||
|
||||
## delete() / deleteAll() -- Remove Memories
|
||||
@@ -241,7 +221,7 @@ client.delete_all(user_id="alice") # Irreversible bulk delete
|
||||
**TypeScript:**
|
||||
```typescript
|
||||
await client.delete("ea925981-...");
|
||||
await client.deleteAll({ user_id: "alice" });
|
||||
await client.deleteAll({ userId: "alice" });
|
||||
```
|
||||
|
||||
---
|
||||
@@ -301,10 +281,73 @@ data = client.get_memory_export(memory_export_id=export["id"])
|
||||
2. **SQL operators rejected** -- use `gte`, `lt`, etc. Not `>=`, `<`.
|
||||
3. **Metadata filtering is limited** -- only top-level keys with `eq`, `contains`, `ne`.
|
||||
4. **Wildcard `*` excludes null** -- only matches non-null values.
|
||||
5. **Default threshold is 0.3** -- increase for stricter matching.
|
||||
5. **Default threshold is 0.1** -- increase for stricter matching.
|
||||
6. **Async processing** -- memories process asynchronously. Wait 2-3s after `add()` before searching.
|
||||
7. **Immutable memories** -- cannot be updated or deleted once created.
|
||||
|
||||
## Naming Conventions
|
||||
|
||||
Python uses `snake_case` (`user_id`, `memory_id`, `get_all`). TypeScript uses `camelCase` for methods (`getAll`, `deleteAll`, `batchUpdate`) but `snake_case` for API parameters (`user_id`, `agent_id`).
|
||||
Python uses `snake_case` everywhere (`user_id`, `memory_id`, `get_all`). TypeScript uses `camelCase` for methods (`getAll`, `deleteAll`, `batchUpdate`) and top-level parameters (`userId`, `topK`, `pageSize`), but filter keys use `snake_case` (`user_id`, `agent_id`).
|
||||
|
||||
---
|
||||
|
||||
## v2 to v3 Migration
|
||||
|
||||
### Breaking Changes in v3
|
||||
|
||||
**1. Entity IDs in search() and getAll()**
|
||||
|
||||
v3 requires entity IDs (`user_id`, `agent_id`, `run_id`) inside `filters` instead of as top-level parameters:
|
||||
|
||||
```python
|
||||
# v2 (deprecated)
|
||||
client.search("query", user_id="alice")
|
||||
client.get_all(user_id="alice")
|
||||
|
||||
# v3
|
||||
client.search("query", filters={"user_id": "alice"})
|
||||
client.get_all(filters={"user_id": "alice"})
|
||||
```
|
||||
|
||||
```typescript
|
||||
// v2 (deprecated)
|
||||
await client.search("query", { user_id: "alice" });
|
||||
await client.getAll({ user_id: "alice" });
|
||||
|
||||
// v3
|
||||
await client.search("query", { filters: { user_id: "alice" } });
|
||||
await client.getAll({ filters: { user_id: "alice" } });
|
||||
```
|
||||
|
||||
**2. TypeScript Parameter Naming**
|
||||
|
||||
v3 TypeScript uses camelCase for all parameters:
|
||||
|
||||
| v2 | v3 |
|
||||
|----|-----|
|
||||
| `user_id` | `userId` |
|
||||
| `agent_id` | `agentId` |
|
||||
| `run_id` | `runId` |
|
||||
| `top_k` | `topK` |
|
||||
| `page_size` | `pageSize` |
|
||||
|
||||
**3. Default Values Changed**
|
||||
|
||||
| Parameter | v2 Default | v3 Default |
|
||||
|-----------|------------|------------|
|
||||
| `threshold` | 0.3 | 0.1 |
|
||||
| `rerank` | (not specified) | `false` |
|
||||
|
||||
**4. Removed Parameters**
|
||||
|
||||
The following parameters are no longer supported:
|
||||
|
||||
| Parameter | Status |
|
||||
|-----------|--------|
|
||||
| `enable_graph` | Removed from add/search/getAll |
|
||||
| `keyword_search` | Removed from search |
|
||||
| `filter_memories` | Removed |
|
||||
| `immutable` | Removed from add |
|
||||
| `expiration_date` | Removed from add |
|
||||
| `includes` | Removed from add |
|
||||
| `excludes` | Removed from add |
|
||||
| `async_mode` | Removed from add |
|
||||
|
||||
@@ -39,7 +39,7 @@ Use these known facts about the user to personalize your response:
|
||||
{context if context else 'No prior context yet.'}"""
|
||||
|
||||
response = openai_client.chat.completions.create(
|
||||
model="gpt-4.1-nano-2025-04-14",
|
||||
model="gpt-5-mini",
|
||||
messages=[
|
||||
{"role": "system", "content": system_prompt},
|
||||
{"role": "user", "content": user_input},
|
||||
@@ -72,14 +72,14 @@ const openai = new OpenAI();
|
||||
|
||||
async function chat(userInput: string, userId: string): Promise<string> {
|
||||
// 1. Retrieve relevant memories
|
||||
const memories = await mem0.search(userInput, { user_id: userId });
|
||||
const memories = await mem0.search(userInput, { filters: { user_id: userId } });
|
||||
const context = memories.results
|
||||
?.map((m: any) => `- ${m.memory}`)
|
||||
.join('\n') || 'No prior context yet.';
|
||||
|
||||
// 2. Generate response with memory context
|
||||
const response = await openai.chat.completions.create({
|
||||
model: 'gpt-4.1-nano-2025-04-14',
|
||||
model: 'gpt-5-mini',
|
||||
messages: [
|
||||
{ role: 'system', content: `You are Ray, a personal fitness coach.\nUser context:\n${context}` },
|
||||
{ role: 'user', content: userInput },
|
||||
@@ -90,7 +90,7 @@ async function chat(userInput: string, userId: string): Promise<string> {
|
||||
// 3. Store interaction
|
||||
await mem0.add(
|
||||
[{ role: 'user', content: userInput }, { role: 'assistant', content: reply }],
|
||||
{ user_id: userId }
|
||||
{ userId: userId }
|
||||
);
|
||||
return reply;
|
||||
}
|
||||
@@ -182,7 +182,7 @@ await client.updateProject({
|
||||
async function logInteraction(userId: string, message: string, priority = 'normal') {
|
||||
await client.add(
|
||||
[{ role: 'user', content: message }],
|
||||
{ user_id: userId, metadata: { priority, source: 'support_chat' } }
|
||||
{ userId: userId, metadata: { priority, source: 'support_chat' } }
|
||||
);
|
||||
}
|
||||
|
||||
@@ -230,7 +230,7 @@ def consult(user_id: str, question: str) -> str:
|
||||
context = "\n".join([f"- {m['memory']}" for m in memories.get("results", [])])
|
||||
|
||||
response = openai_client.chat.completions.create(
|
||||
model="gpt-4.1-nano-2025-04-14",
|
||||
model="gpt-5-mini",
|
||||
messages=[
|
||||
{"role": "system", "content": f"You are a health coach. Patient context:\n{context}"},
|
||||
{"role": "user", "content": question},
|
||||
@@ -264,20 +264,20 @@ const openai = new OpenAI();
|
||||
async function savePatientInfo(userId: string, info: string) {
|
||||
await mem0.add(
|
||||
[{ role: 'user', content: info }],
|
||||
{ user_id: userId, run_id: 'healthcare_session', metadata: { type: 'patient_information' } }
|
||||
{ userId: userId, runId: 'healthcare_session', metadata: { type: 'patient_information' } }
|
||||
);
|
||||
}
|
||||
|
||||
async function consult(userId: string, question: string): Promise<string> {
|
||||
const memories = await mem0.search(question, {
|
||||
user_id: userId,
|
||||
top_k: 5,
|
||||
filters: { user_id: userId },
|
||||
topK: 5,
|
||||
threshold: 0.7,
|
||||
});
|
||||
const context = memories.results?.map((m: any) => `- ${m.memory}`).join('\n') || '';
|
||||
|
||||
const response = await openai.chat.completions.create({
|
||||
model: 'gpt-4.1-nano-2025-04-14',
|
||||
model: 'gpt-5-mini',
|
||||
messages: [
|
||||
{ role: 'system', content: `You are a health coach. Patient context:\n${context}` },
|
||||
{ role: 'user', content: question },
|
||||
@@ -287,7 +287,7 @@ async function consult(userId: string, question: string): Promise<string> {
|
||||
|
||||
await mem0.add(
|
||||
[{ role: 'user', content: question }, { role: 'assistant', content: reply }],
|
||||
{ user_id: userId, run_id: 'healthcare_session' }
|
||||
{ userId: userId, runId: 'healthcare_session' }
|
||||
);
|
||||
return reply;
|
||||
}
|
||||
@@ -333,7 +333,7 @@ def draft_content(user_id: str, topic: str) -> str:
|
||||
style_context = "\n".join([f"- {m['memory']}" for m in prefs.get("results", [])])
|
||||
|
||||
response = openai_client.chat.completions.create(
|
||||
model="gpt-4.1-nano-2025-04-14",
|
||||
model="gpt-5-mini",
|
||||
messages=[
|
||||
{"role": "system", "content": f"Write content matching these style preferences:\n{style_context}"},
|
||||
{"role": "user", "content": f"Write a blog post about: {topic}"},
|
||||
@@ -359,7 +359,7 @@ const openai = new OpenAI();
|
||||
async function storePreferences(userId: string, preferences: string) {
|
||||
await mem0.add(
|
||||
[{ role: 'user', content: preferences }],
|
||||
{ user_id: userId, run_id: 'editing_session', metadata: { type: 'preferences' } }
|
||||
{ userId: userId, runId: 'editing_session', metadata: { type: 'preferences' } }
|
||||
);
|
||||
}
|
||||
|
||||
@@ -370,7 +370,7 @@ async function draftContent(userId: string, topic: string): Promise<string> {
|
||||
const styleContext = prefs.results?.map((m: any) => `- ${m.memory}`).join('\n') || '';
|
||||
|
||||
const response = await openai.chat.completions.create({
|
||||
model: 'gpt-4.1-nano-2025-04-14',
|
||||
model: 'gpt-5-mini',
|
||||
messages: [
|
||||
{ role: 'system', content: `Write content matching these preferences:\n${styleContext}` },
|
||||
{ role: 'user', content: `Write a blog post about: ${topic}` },
|
||||
@@ -465,10 +465,10 @@ async function storeScopedMemory(
|
||||
userId: string, agentId: string, runId: string, appId: string
|
||||
) {
|
||||
await client.add(messages, {
|
||||
user_id: userId,
|
||||
agent_id: agentId,
|
||||
run_id: runId,
|
||||
app_id: appId,
|
||||
userId: userId,
|
||||
agentId: agentId,
|
||||
runId: runId,
|
||||
appId: appId,
|
||||
});
|
||||
}
|
||||
|
||||
@@ -520,7 +520,7 @@ def personalized_search(user_id: str, query: str, search_results: list) -> str:
|
||||
user_context = "\n".join([f"- {m['memory']}" for m in memories.get("results", [])])
|
||||
|
||||
response = openai_client.chat.completions.create(
|
||||
model="gpt-4.1-nano-2025-04-14",
|
||||
model="gpt-5-mini",
|
||||
messages=[
|
||||
{"role": "system", "content": f"Personalize search results using user context:\n{user_context}"},
|
||||
{"role": "user", "content": f"Query: {query}\n\nSearch results:\n{search_results}"},
|
||||
@@ -551,11 +551,11 @@ const mem0 = new MemoryClient({ apiKey: process.env.MEM0_API_KEY! });
|
||||
const openai = new OpenAI();
|
||||
|
||||
async function personalizedSearch(userId: string, query: string, searchResults: string[]): Promise<string> {
|
||||
const memories = await mem0.search(query, { user_id: userId, top_k: 5 });
|
||||
const memories = await mem0.search(query, { filters: { user_id: userId }, topK: 5 });
|
||||
const context = memories.results?.map((m: any) => `- ${m.memory}`).join('\n') || '';
|
||||
|
||||
const response = await openai.chat.completions.create({
|
||||
model: 'gpt-4.1-nano-2025-04-14',
|
||||
model: 'gpt-5-mini',
|
||||
messages: [
|
||||
{ role: 'system', content: `Personalize results using user context:\n${context}` },
|
||||
{ role: 'user', content: `Query: ${query}\nResults: ${searchResults.join(', ')}` },
|
||||
@@ -563,7 +563,7 @@ async function personalizedSearch(userId: string, query: string, searchResults:
|
||||
});
|
||||
const reply = response.choices[0].message.content!;
|
||||
|
||||
await mem0.add([{ role: 'user', content: query }], { user_id: userId });
|
||||
await mem0.add([{ role: 'user', content: query }], { userId: userId });
|
||||
return reply;
|
||||
}
|
||||
```
|
||||
@@ -631,14 +631,14 @@ const client = new MemoryClient({ apiKey: process.env.MEM0_API_KEY! });
|
||||
async function storeEmail(userId: string, sender: string, subject: string, body: string, date: string) {
|
||||
await client.add(
|
||||
[{ role: 'user', content: `Email from ${sender}: ${subject}\n\n${body}` }],
|
||||
{ user_id: userId, metadata: { email_type: 'incoming', sender, subject, date } }
|
||||
{ userId: userId, metadata: { email_type: 'incoming', sender, subject, date } }
|
||||
);
|
||||
}
|
||||
|
||||
async function searchEmails(userId: string, query: string) {
|
||||
return client.search(query, {
|
||||
filters: { AND: [{ user_id: userId }, { categories: { contains: 'email' } }] },
|
||||
top_k: 10,
|
||||
topK: 10,
|
||||
});
|
||||
}
|
||||
```
|
||||
|
||||
Reference in New Issue
Block a user