chore: merge origin/main into mintlify/af82bda4 and resolve conflicts
This commit is contained in:
@@ -99,16 +99,23 @@ results = client.search(
|
||||
|
||||
### Recommended Configurations
|
||||
|
||||
`rerank` is the only lever here that changes result *order*. `filters`, `top_k`, and `threshold` change *which* memories come back, not how they're ordered. The two functions below send the same query and filters; the only difference is the `rerank` flag.
|
||||
|
||||
<CodeGroup>
|
||||
```python Python
|
||||
# Basic search - good for exploration
|
||||
# Fast path - use for exploratory search, or anywhere the user scans a list
|
||||
# of results instead of trusting result #1 (dashboards, "show me everything
|
||||
# about X" style queries). No reranking overhead.
|
||||
def quick_search(query, user_id):
|
||||
return client.search(
|
||||
query=query,
|
||||
filters={"user_id": user_id},
|
||||
)
|
||||
|
||||
# Reranked search - good when result order matters
|
||||
# Precision path - use when only the top result reaches the user, e.g. an
|
||||
# agent that injects a single fact into a prompt. Reranking (see above)
|
||||
# re-scores every match and moves the closest one to position 1, at the
|
||||
# cost of ~150-200ms added latency.
|
||||
def standard_search(query, user_id):
|
||||
return client.search(
|
||||
query=query,
|
||||
@@ -118,14 +125,19 @@ def standard_search(query, user_id):
|
||||
```
|
||||
|
||||
```javascript JavaScript
|
||||
// Basic search - good for exploration
|
||||
// Fast path - use for exploratory search, or anywhere the user scans a list
|
||||
// of results instead of trusting result #1 (dashboards, "show me everything
|
||||
// about X" style queries). No reranking overhead.
|
||||
function quickSearch(query, userId) {
|
||||
return client.search(query, {
|
||||
filters: { user_id: userId },
|
||||
});
|
||||
}
|
||||
|
||||
// Reranked search - good when result order matters
|
||||
// Precision path - use when only the top result reaches the user, e.g. an
|
||||
// agent that injects a single fact into a prompt. Reranking (see above)
|
||||
// re-scores every match and moves the closest one to position 1, at the
|
||||
// cost of ~150-200ms added latency.
|
||||
function standardSearch(query, userId) {
|
||||
return client.search(query, {
|
||||
filters: { user_id: userId },
|
||||
@@ -135,6 +147,8 @@ function standardSearch(query, userId) {
|
||||
```
|
||||
</CodeGroup>
|
||||
|
||||
**What changes in the response:** both calls return the same fields on each memory (see the [Search Memories API reference](/api-reference/memory/search-memories) for the full response shape). The only difference is the *order* of the `results` array, the same effect shown in the [Reranking example above](#reranking): `quick_search` returns results ranked by raw similarity, `standard_search` returns the reranked order.
|
||||
|
||||
## Best Practices
|
||||
|
||||
### Do
|
||||
|
||||
@@ -75,7 +75,7 @@ print(response)
|
||||
```
|
||||
</CodeGroup>
|
||||
|
||||
This "Updated custom categories" message is specific to a PATCH-style partial update, which is what `client.project.update()` sends. Calling the raw API with a full PUT instead returns a generic `{"message": "Project updated successfully."}`, regardless of which fields changed.
|
||||
Treat the `message` string as informational. The project endpoint accepts `PATCH` only, and its documented response is the generic `{"message": "Project updated successfully"}`. Confirm an update by reading the field back, as in the next step, rather than by matching on the message.
|
||||
|
||||
### 2. Confirm the active catalog
|
||||
|
||||
|
||||
@@ -1,6 +1,7 @@
|
||||
---
|
||||
title: Custom Instructions
|
||||
description: 'Guide Mem0 Platform memory extraction with natural language project-level instructions that decide what conversation details to store or ignore.'
|
||||
title: "Platform Custom Instructions"
|
||||
sidebarTitle: "Custom Instructions"
|
||||
description: 'Control how Mem0 extracts and stores memories using natural language guidelines'
|
||||
---
|
||||
|
||||
## What are Custom Instructions?
|
||||
@@ -95,6 +96,100 @@ Exclude:
|
||||
- [Irrelevant information]
|
||||
```
|
||||
|
||||
## Agent Custom Instructions
|
||||
|
||||
`custom_instructions` applies to every memory your project extracts, no matter whose it is. But what is worth remembering about an agent is rarely what is worth remembering about a user: an agent's useful memories are things like which tools fail, which retry strategies work, and how a given environment behaves, not personal preferences.
|
||||
|
||||
`agent_custom_instructions` is an optional second set of extraction rules that applies only to agent-scoped memories.
|
||||
|
||||
Available from Python SDK `v2.0.17` and TypeScript SDK `v3.1.5`. Upgrade first if you are on an earlier release.
|
||||
|
||||
Set it on the project alongside `custom_instructions`:
|
||||
|
||||
<CodeGroup>
|
||||
```python Python
|
||||
client.project.update(
|
||||
custom_instructions="Extract the user's preferences, goals, and constraints.",
|
||||
agent_custom_instructions=(
|
||||
"Extract operational lessons for the agent:\n"
|
||||
"- Tools that failed and the error returned\n"
|
||||
"- Retry or fallback strategies that worked\n"
|
||||
"- Environment quirks worth recalling on the next run\n\n"
|
||||
"Exclude: user preferences, personal details."
|
||||
),
|
||||
)
|
||||
```
|
||||
|
||||
```javascript JavaScript
|
||||
await client.updateProject({
|
||||
customInstructions: "Extract the user's preferences, goals, and constraints.",
|
||||
agentCustomInstructions: `Extract operational lessons for the agent:
|
||||
- Tools that failed and the error returned
|
||||
- Retry or fallback strategies that worked
|
||||
- Environment quirks worth recalling on the next run
|
||||
|
||||
Exclude: user preferences, personal details.`,
|
||||
});
|
||||
```
|
||||
</CodeGroup>
|
||||
|
||||
### Which instructions apply
|
||||
|
||||
Which set governs an `add()` call depends on the entity IDs you pass with it:
|
||||
|
||||
| The add call passes | Instructions applied |
|
||||
|---------------------|----------------------|
|
||||
| `user_id` only | `custom_instructions` |
|
||||
| `agent_id` only | `agent_custom_instructions` |
|
||||
| `user_id` **and** `agent_id` | `agent_custom_instructions` govern the memories attributed to the assistant; `custom_instructions` govern the rest |
|
||||
|
||||
`agent_custom_instructions` is unset by default. While it is unset, `custom_instructions` applies to every memory, so projects that don't set it behave exactly as they did before.
|
||||
|
||||
### Overriding for a single call
|
||||
|
||||
Both fields are also accepted per request, overriding the project setting for that `add()` only:
|
||||
|
||||
<CodeGroup>
|
||||
```python Python
|
||||
client.add(
|
||||
messages,
|
||||
filters={"agent_id": "support-agent"},
|
||||
agent_custom_instructions="Only remember which tools errored and why.",
|
||||
)
|
||||
```
|
||||
|
||||
```javascript JavaScript
|
||||
await client.add(messages, {
|
||||
agentId: "support-agent",
|
||||
agentCustomInstructions: "Only remember which tools errored and why.",
|
||||
});
|
||||
```
|
||||
</CodeGroup>
|
||||
|
||||
### Reading and clearing
|
||||
|
||||
<CodeGroup>
|
||||
```python Python
|
||||
# Read the current value
|
||||
response = client.project.get(fields=["agent_custom_instructions"])
|
||||
print(response["agent_custom_instructions"])
|
||||
|
||||
# Clear it; agent memories fall back to custom_instructions
|
||||
client.project.update(agent_custom_instructions="")
|
||||
```
|
||||
|
||||
```javascript JavaScript
|
||||
// Read the current value
|
||||
const response = await client.getProject({
|
||||
fields: ["agentCustomInstructions"],
|
||||
});
|
||||
console.log(response.agentCustomInstructions);
|
||||
|
||||
// Clear it; agent memories fall back to customInstructions
|
||||
await client.updateProject({ agentCustomInstructions: "" });
|
||||
```
|
||||
</CodeGroup>
|
||||
|
||||
## Real-World Examples
|
||||
|
||||
<Tabs>
|
||||
|
||||
@@ -1,6 +1,6 @@
|
||||
---
|
||||
title: Dream
|
||||
description: "Dream keeps Mem0 user memory sharp by distilling recurring patterns, retiring outdated facts, and merging duplicates in the background."
|
||||
description: "Dream keeps a user's memory clean over time by distilling recurring patterns, retiring outdated facts, and merging duplicates in the background."
|
||||
---
|
||||
|
||||
# Dream
|
||||
|
||||
@@ -64,7 +64,7 @@ client.project.update(decay=True)
|
||||
```
|
||||
|
||||
```javascript JavaScript
|
||||
await client.project.update({ decay: true });
|
||||
await client.updateProject({ decay: true });
|
||||
```
|
||||
|
||||
```bash cURL
|
||||
@@ -75,32 +75,32 @@ curl -X PATCH https://api.mem0.ai/api/v1/orgs/organizations/$ORG_ID/projects/$PR
|
||||
```
|
||||
|
||||
```json Response
|
||||
{ "message": "Updated decay" }
|
||||
{ "message": "Project updated successfully" }
|
||||
```
|
||||
</CodeGroup>
|
||||
|
||||
### 2. Confirm the state
|
||||
|
||||
`decay` is returned on every project read; there is currently no way to narrow the response to just this field, so read the full project object and pick out `decay`.
|
||||
`decay` is returned on every project read. To fetch only this field, use `?fields=decay`.
|
||||
|
||||
<CodeGroup>
|
||||
```python Python
|
||||
response = client.project.get()
|
||||
response = client.project.get(fields=["decay"])
|
||||
print(response["decay"])
|
||||
```
|
||||
|
||||
```javascript JavaScript
|
||||
const response = await client.project.get();
|
||||
const response = await client.getProject({ fields: ["decay"] });
|
||||
console.log(response.decay);
|
||||
```
|
||||
|
||||
```bash cURL
|
||||
curl "https://api.mem0.ai/api/v1/orgs/organizations/$ORG_ID/projects/$PROJECT_ID/" \
|
||||
curl "https://api.mem0.ai/api/v1/orgs/organizations/$ORG_ID/projects/$PROJECT_ID/?fields=decay" \
|
||||
-H "Authorization: Token $MEM0_API_KEY"
|
||||
```
|
||||
|
||||
```json Response
|
||||
{ "decay": true, "...": "full project object" }
|
||||
{ "decay": true }
|
||||
```
|
||||
</CodeGroup>
|
||||
|
||||
@@ -114,7 +114,7 @@ client.project.update(decay=False)
|
||||
```
|
||||
|
||||
```javascript JavaScript
|
||||
await client.project.update({ decay: false });
|
||||
await client.updateProject({ decay: false });
|
||||
```
|
||||
|
||||
```bash cURL
|
||||
|
||||
@@ -1,6 +1,7 @@
|
||||
---
|
||||
title: Multimodal Support
|
||||
description: Add images, PDFs, and other documents alongside text on the Mem0 Platform so agents can extract and recall insights from mixed visual content.
|
||||
title: "Platform Multimodal Support"
|
||||
sidebarTitle: "Multimodal Support"
|
||||
description: Integrate images and documents into your interactions with Mem0
|
||||
---
|
||||
|
||||
Mem0 extends its capabilities beyond text by supporting multimodal data, including images and documents. With this feature, users can seamlessly integrate visual and document content into their interactions, allowing Mem0 to extract relevant information from various media types and enrich the memory system.
|
||||
@@ -76,18 +77,8 @@ await client.add(messages, { userId: "alice" })
|
||||
|
||||
```json Output
|
||||
{
|
||||
"results": [
|
||||
{
|
||||
"memory": "Name is Alice",
|
||||
"event": "ADD",
|
||||
"id": "7ae113a3-3cb5-46e9-b6f7-486c36391847"
|
||||
},
|
||||
{
|
||||
"memory": "Likes large pizza with toppings including cherry tomatoes, black olives, green spinach, yellow bell peppers, diced ham, and sliced mushrooms",
|
||||
"event": "ADD",
|
||||
"id": "56545065-7dee-4acf-8bf2-a5b2535aabb3"
|
||||
}
|
||||
]
|
||||
"event_id": "evt-uuid",
|
||||
"status": "PENDING"
|
||||
}
|
||||
```
|
||||
</CodeGroup>
|
||||
|
||||
@@ -82,11 +82,11 @@ client.add(messages, { userId: "user1", timestamp: unixTimestamp })
|
||||
```
|
||||
|
||||
```bash cURL
|
||||
curl -X POST "https://api.mem0.ai/v1/memories/" \
|
||||
curl -X POST "https://api.mem0.ai/v3/memories/add/" \
|
||||
-H "Authorization: Token your-api-key" \
|
||||
-H "Content-Type: application/json" \
|
||||
-d '{
|
||||
"messages": [{"role": "user", "content": "I'm travelling to SF"}],
|
||||
"messages": [{"role": "user", "content": "Travelling to SF"}],
|
||||
"user_id": "user1",
|
||||
"timestamp": 1721577600
|
||||
}'
|
||||
@@ -94,13 +94,8 @@ curl -X POST "https://api.mem0.ai/v1/memories/" \
|
||||
|
||||
```json Output
|
||||
{
|
||||
"results": [
|
||||
{
|
||||
"id": "a1b2c3d4-e5f6-4g7h-8i9j-k0l1m2n3o4p5",
|
||||
"data": {"memory": "Travelling to SF"},
|
||||
"event": "ADD"
|
||||
}
|
||||
]
|
||||
"event_id": "evt-uuid",
|
||||
"status": "PENDING"
|
||||
}
|
||||
```
|
||||
|
||||
|
||||
@@ -29,6 +29,46 @@ Filters use a nested JSON structure with logical operators at the root:
|
||||
}
|
||||
```
|
||||
|
||||
A single bare condition needs no wrapper:
|
||||
|
||||
```python
|
||||
# Works: one condition, no wrapper needed
|
||||
filters = {"user_id": "user_123"}
|
||||
```
|
||||
|
||||
Sibling top-level keys in a flat object are accepted too: the API implicitly ANDs them, so the flat form and the explicit `AND` form are equivalent:
|
||||
|
||||
```python
|
||||
# Works: sibling keys are implicitly ANDed
|
||||
filters = {
|
||||
"user_id": "user_123",
|
||||
"categories": {"in": ["finance"]}
|
||||
}
|
||||
|
||||
# Equivalent, explicit form
|
||||
filters = {
|
||||
"AND": [
|
||||
{"user_id": "user_123"},
|
||||
{"categories": {"in": ["finance"]}}
|
||||
]
|
||||
}
|
||||
```
|
||||
|
||||
Reach for an explicit `AND`, `OR`, or `NOT` wrapper when you need `OR` or `NOT` semantics, or when you need to nest conditions. What the API does reject is an unrecognized top-level key:
|
||||
|
||||
```python
|
||||
# Rejected: unknown top-level key
|
||||
filters = {"user_id": "user_123", "bogus_key": "z"}
|
||||
# 400: Top-level key must be a logical operator or an allowed field:
|
||||
# ['AND', 'OR', 'NOT', 'user_id', 'agent_id', 'app_id', 'run_id',
|
||||
# 'created_at', 'updated_at', 'timestamp', 'expiration_date', 'text',
|
||||
# 'categories', 'metadata', 'keywords_search', 'memory_ids', 'keywords']
|
||||
```
|
||||
|
||||
<Callout type="info" icon="cloud" color="#00A8FF">
|
||||
Both the hosted Platform API and the self-hosted OSS SDK implicitly AND sibling top-level keys, so the flat and explicit `AND` forms behave the same way on either. The real differences: Platform validates each top-level key against a fixed allow-list and returns a 400 for anything else, and Platform has no `nin` operator. See [Enhanced Metadata Filtering](/open-source/features/metadata-filtering) for the OSS grammar.
|
||||
</Callout>
|
||||
|
||||
## Available fields and operators
|
||||
|
||||
### Entity fields
|
||||
@@ -42,14 +82,15 @@ Filters use a nested JSON structure with logical operators at the root:
|
||||
### Time fields
|
||||
| Field | Operators | Example |
|
||||
|-------|-----------|---------|
|
||||
| `created_at` | `gt`, `gte`, `lt`, `lte`, `eq`, `ne` | `{"created_at": {"gte": "2024-01-01"}}` |
|
||||
| `updated_at` | `gt`, `gte`, `lt`, `lte`, `eq`, `ne` | `{"updated_at": {"lt": "2024-12-31"}}` |
|
||||
| `timestamp` | `gt`, `gte`, `lt`, `lte`, `eq`, `ne` | `{"timestamp": {"gt": "2024-01-01"}}` |
|
||||
| `created_at` | `gt`, `gte`, `lt`, `lte`, `ne`, `in`. Explicit `eq` is rejected, pass a bare value instead | `{"created_at": {"gte": "2024-01-01"}}` |
|
||||
| `updated_at` | `gt`, `gte`, `lt`, `lte`, `ne`, `in`. Explicit `eq` is rejected, pass a bare value instead | `{"updated_at": {"lt": "2024-12-31"}}` |
|
||||
| `timestamp` | `gt`, `gte`, `lt`, `lte`, `ne`, `in`. Explicit `eq` is rejected, pass a bare value instead | `{"timestamp": {"gt": "2024-01-01"}}` |
|
||||
| `expiration_date` | `gt`, `gte`, `lt`, `lte`, `ne`, `in`. Explicit `eq` is rejected, pass a bare value instead | `{"expiration_date": {"lte": "2026-12-31"}}` |
|
||||
|
||||
### Content fields
|
||||
| Field | Operators | Example |
|
||||
|-------|-----------|---------|
|
||||
| `categories` | `eq`, `ne`, `in` (matches any category in the list), `contains` (case-insensitive) | `{"categories": {"in": ["finance"]}}` |
|
||||
| `categories` | `in` (takes a list, matches any category in it), `contains` (case-insensitive). `eq` and `ne` are rejected | `{"categories": {"in": ["finance"]}}` |
|
||||
| `metadata` | `eq`, `ne`, `contains` | `{"metadata": {"key": "value"}}` |
|
||||
| `keywords` | `contains` (case-sensitive), `icontains` (case-insensitive) | `{"keywords": {"icontains": "invoice"}}` |
|
||||
|
||||
@@ -66,6 +107,14 @@ The `*` wildcard matches any non-null value. Records with null values for that f
|
||||
Use operator keywords exactly as shown (`eq`, `ne`, `gte`, etc.). SQL-style symbols such as `>=` or `!=` are rejected by the Platform API.
|
||||
</Callout>
|
||||
|
||||
<Callout type="warning" icon="exclamation-triangle" color="#E74C3C">
|
||||
There is no `nin` ("not in") operator on Platform. It is an OSS-only operator; see [Enhanced Metadata Filtering](/open-source/features/metadata-filtering). To exclude a set of values on Platform, wrap an `in` clause in `NOT`:
|
||||
|
||||
```python
|
||||
{"NOT": {"categories": {"in": ["spam", "test"]}}}
|
||||
```
|
||||
</Callout>
|
||||
|
||||
## Common filter patterns
|
||||
|
||||
Use these ready-made filters to target typical retrieval scenarios without rebuilding logic from scratch.
|
||||
@@ -328,7 +377,7 @@ Level up foundational patterns with compound filters that coordinate entity scop
|
||||
## Best practices
|
||||
|
||||
<Callout type="tip" icon="lightbulb" color="#26A17B">
|
||||
The root does not have to be `AND`, `OR`, or `NOT`. A bare filter like `{"user_id": "alice"}` works on its own; wrap conditions in a logical operator only when you need to combine more than one.
|
||||
The root does not have to be `AND`, `OR`, or `NOT`. A bare filter like `{"user_id": "alice"}` works on its own, and several top-level keys in one flat filter are implicitly ANDed. Wrap conditions in a logical operator when you need OR/NOT semantics or nested grouping.
|
||||
</Callout>
|
||||
|
||||
<Callout type="tip" icon="lightbulb" color="#26A17B">
|
||||
@@ -392,7 +441,7 @@ A filter object with both an `AND` key and a sibling `OR` key at the same level
|
||||
|
||||
<AccordionGroup>
|
||||
<Accordion title="Do I need AND/OR/NOT?">
|
||||
No. A bare filter like `{"user_id": "u1"}` works on its own. Add `AND`, `OR`, or `NOT` only when you need to combine more than one condition.
|
||||
No. A bare filter like `{"user_id": "u1"}` works on its own, and several top-level keys in one flat filter like `{"user_id": "u1", "agent_id": "a1"}` are implicitly ANDed. Reach for `AND`, `OR`, or `NOT` when you need OR/NOT semantics or nested grouping, not merely to combine conditions.
|
||||
</Accordion>
|
||||
|
||||
<Accordion title="What does * match?">
|
||||
@@ -421,8 +470,8 @@ A filter object with both an `AND` key and a sibling `OR` key at the same level
|
||||
"AND": [
|
||||
{"user_id": "user_123"},
|
||||
{"OR": [
|
||||
{"categories": "finance"},
|
||||
{"categories": "health"}
|
||||
{"categories": {"in": ["finance"]}},
|
||||
{"categories": {"in": ["health"]}}
|
||||
]}
|
||||
]
|
||||
}
|
||||
|
||||
Reference in New Issue
Block a user