mirror of
https://github.com/supermemoryai/supermemory.git
synced 2026-10-07 02:58:11 +00:00
docs: staleness sweep — current model IDs, AI SDK APIs, one search signature
Fixes across existing pages: stale claude-3-sonnet -> current models, deprecated ai/react + toAIStreamResponse -> current AI SDK APIs, five divergent search signatures unified to client.search.memories (v4) / client.search.documents (v3), singular containerTag in v4 contexts, from-zep containerTag type error, canonical processing-status enum, corrected 'v4 has no SDK' claim, internal links re-pointed at final destinations. Co-Authored-By: Claude Fable 5 <noreply@anthropic.com>
This commit is contained in:
parent
4970ad4b2c
commit
492e09bae2
57 changed files with 95 additions and 8082 deletions
|
|
@ -385,7 +385,7 @@ When you add content, Supermemory:
|
|||
Track progress with `GET /v3/documents/{id}`:
|
||||
```typescript
|
||||
const doc = await client.documents.get("abc123");
|
||||
console.log(doc.status); // "queued" | "processing" | "done"
|
||||
console.log(doc.status); // "queued" | "extracting" | "chunking" | "embedding" | "indexing" | "done" | "failed"
|
||||
```
|
||||
|
||||
<AccordionGroup>
|
||||
|
|
@ -479,4 +479,4 @@ console.log(doc.status); // "queued" | "processing" | "done"
|
|||
|
||||
- [Search Memories](/search) — Query your content
|
||||
- [User Profiles](/user-profiles) — Get user context
|
||||
- [Organizing & Filtering](/concepts/filtering) — Container tags and metadata
|
||||
- [Organizing & Filtering](/concepts/hybrid-search) — Container tags and metadata
|
||||
|
|
|
|||
|
|
@ -1,278 +0,0 @@
|
|||
---
|
||||
title: "Basic Usage"
|
||||
description: "Simple examples of adding text content to Supermemory"
|
||||
---
|
||||
|
||||
Learn how to add basic text content to Supermemory with simple, practical examples.
|
||||
|
||||
## Add Simple Text
|
||||
|
||||
The most basic operation - adding plain text content.
|
||||
|
||||
<CodeGroup>
|
||||
|
||||
```typescript TypeScript
|
||||
const response = await client.add({
|
||||
content: "Artificial intelligence is transforming how we work and live"
|
||||
});
|
||||
|
||||
console.log(response);
|
||||
// Output: { id: "abc123", status: "queued" }
|
||||
```
|
||||
|
||||
```python Python
|
||||
response = client.add(
|
||||
content="Artificial intelligence is transforming how we work and live"
|
||||
)
|
||||
|
||||
print(response)
|
||||
# Output: {"id": "abc123", "status": "queued"}
|
||||
```
|
||||
|
||||
```bash cURL
|
||||
curl -X POST "https://api.supermemory.ai/v3/documents" \
|
||||
-H "Authorization: Bearer $SUPERMEMORY_API_KEY" \
|
||||
-H "Content-Type: application/json" \
|
||||
-d '{
|
||||
"content": "Artificial intelligence is transforming how we work and live"
|
||||
}'
|
||||
```
|
||||
|
||||
</CodeGroup>
|
||||
|
||||
## Add with Container Tags
|
||||
|
||||
Group related content using container tags.
|
||||
|
||||
<CodeGroup>
|
||||
|
||||
```typescript TypeScript
|
||||
const response = await client.add({
|
||||
content: "Q4 2024 revenue exceeded projections by 15%",
|
||||
containerTag: "financial_reports"
|
||||
});
|
||||
|
||||
console.log(response.id);
|
||||
// Output: xyz789
|
||||
```
|
||||
|
||||
```python Python
|
||||
response = client.add(
|
||||
content="Q4 2024 revenue exceeded projections by 15%",
|
||||
container_tag="financial_reports"
|
||||
)
|
||||
|
||||
print(response['id'])
|
||||
# Output: xyz789
|
||||
```
|
||||
|
||||
```bash cURL
|
||||
curl -X POST "https://api.supermemory.ai/v3/documents" \
|
||||
-H "Authorization: Bearer $SUPERMEMORY_API_KEY" \
|
||||
-H "Content-Type: application/json" \
|
||||
-d '{
|
||||
"content": "Q4 2024 revenue exceeded projections by 15%",
|
||||
"containerTag": "financial_reports"
|
||||
}'
|
||||
|
||||
# Response: {"id": "xyz789", "status": "queued"}
|
||||
```
|
||||
|
||||
</CodeGroup>
|
||||
|
||||
## Add with Metadata
|
||||
|
||||
Attach metadata for better search and filtering.
|
||||
|
||||
<CodeGroup>
|
||||
|
||||
```typescript TypeScript
|
||||
await client.add({
|
||||
content: "New onboarding flow reduces drop-off by 30%",
|
||||
containerTag: "product_updates",
|
||||
metadata: {
|
||||
impact: "high",
|
||||
team: "product"
|
||||
}
|
||||
});
|
||||
```
|
||||
|
||||
```python Python
|
||||
client.add(
|
||||
content="New onboarding flow reduces drop-off by 30%",
|
||||
container_tag="product_updates",
|
||||
metadata={
|
||||
"impact": "high",
|
||||
"team": "product"
|
||||
}
|
||||
)
|
||||
```
|
||||
|
||||
```bash cURL
|
||||
curl -X POST "https://api.supermemory.ai/v3/documents" \
|
||||
-H "Authorization: Bearer $SUPERMEMORY_API_KEY" \
|
||||
-H "Content-Type: application/json" \
|
||||
-d '{
|
||||
"content": "New onboarding flow reduces drop-off by 30%",
|
||||
"containerTag": "product_updates",
|
||||
"metadata": {"impact": "high", "team": "product"}
|
||||
}'
|
||||
```
|
||||
|
||||
</CodeGroup>
|
||||
|
||||
## Add Multiple Documents
|
||||
|
||||
Process multiple related documents.
|
||||
|
||||
<CodeGroup>
|
||||
|
||||
```typescript TypeScript
|
||||
const notes = [
|
||||
"API redesign discussion",
|
||||
"Security audit next month",
|
||||
"New hire starting Monday"
|
||||
];
|
||||
|
||||
const results = await Promise.all(
|
||||
notes.map(note =>
|
||||
client.add({
|
||||
content: note,
|
||||
containerTag: "meeting_2024_01_15"
|
||||
})
|
||||
)
|
||||
);
|
||||
```
|
||||
|
||||
```python Python
|
||||
notes = [
|
||||
"API redesign discussion",
|
||||
"Security audit next month",
|
||||
"New hire starting Monday"
|
||||
]
|
||||
|
||||
for note in notes:
|
||||
client.add(
|
||||
content=note,
|
||||
container_tag="meeting_2024_01_15"
|
||||
)
|
||||
```
|
||||
|
||||
```bash cURL
|
||||
# Add each note with separate requests
|
||||
curl -X POST "https://api.supermemory.ai/v3/documents" \
|
||||
-H "Authorization: Bearer $SUPERMEMORY_API_KEY" \
|
||||
-H "Content-Type: application/json" \
|
||||
-d '{"content": "API redesign discussion", "containerTag": "meeting_2024_01_15"}'
|
||||
```
|
||||
|
||||
</CodeGroup>
|
||||
|
||||
## Add URLs
|
||||
|
||||
Process web pages, YouTube videos, and other URLs automatically.
|
||||
|
||||
<CodeGroup>
|
||||
|
||||
```typescript TypeScript
|
||||
// Web page
|
||||
await client.add({
|
||||
content: "https://example.com/article",
|
||||
containerTag: "articles"
|
||||
});
|
||||
|
||||
// YouTube video (auto-transcribed)
|
||||
await client.add({
|
||||
content: "https://youtube.com/watch?v=dQw4w9WgXcQ",
|
||||
containerTag: "videos"
|
||||
});
|
||||
|
||||
// Google Docs
|
||||
await client.add({
|
||||
content: "https://docs.google.com/document/d/abc123/edit",
|
||||
containerTag: "docs"
|
||||
});
|
||||
```
|
||||
|
||||
```python Python
|
||||
# Web page
|
||||
client.add(
|
||||
content="https://example.com/article",
|
||||
container_tag="articles"
|
||||
)
|
||||
|
||||
# YouTube video (auto-transcribed)
|
||||
client.add(
|
||||
content="https://youtube.com/watch?v=dQw4w9WgXcQ",
|
||||
container_tag="videos"
|
||||
)
|
||||
|
||||
# Google Docs
|
||||
client.add(
|
||||
content="https://docs.google.com/document/d/abc123/edit",
|
||||
container_tag="docs"
|
||||
)
|
||||
```
|
||||
|
||||
```bash cURL
|
||||
# Web page
|
||||
curl -X POST "https://api.supermemory.ai/v3/documents" \
|
||||
-H "Authorization: Bearer $SUPERMEMORY_API_KEY" \
|
||||
-H "Content-Type: application/json" \
|
||||
-d '{"content": "https://example.com/article", "containerTag": "articles"}'
|
||||
|
||||
# YouTube video
|
||||
curl -X POST "https://api.supermemory.ai/v3/documents" \
|
||||
-H "Authorization: Bearer $SUPERMEMORY_API_KEY" \
|
||||
-H "Content-Type: application/json" \
|
||||
-d '{"content": "https://youtube.com/watch?v=dQw4w9WgXcQ", "containerTag": "videos"}'
|
||||
```
|
||||
|
||||
</CodeGroup>
|
||||
|
||||
## Add Markdown Content
|
||||
|
||||
Supermemory preserves markdown formatting.
|
||||
|
||||
<CodeGroup>
|
||||
|
||||
```typescript TypeScript
|
||||
const markdown = `
|
||||
# Project Documentation
|
||||
|
||||
## Features
|
||||
- **Real-time sync**
|
||||
- **AI search**
|
||||
- **Enterprise security**
|
||||
`;
|
||||
|
||||
await client.add({
|
||||
content: markdown,
|
||||
containerTag: "docs"
|
||||
});
|
||||
```
|
||||
|
||||
```python Python
|
||||
markdown = """
|
||||
# Project Documentation
|
||||
|
||||
## Features
|
||||
- **Real-time sync**
|
||||
- **AI search**
|
||||
- **Enterprise security**
|
||||
"""
|
||||
|
||||
client.add(
|
||||
content=markdown,
|
||||
container_tag="docs"
|
||||
)
|
||||
```
|
||||
|
||||
```bash cURL
|
||||
curl -X POST "https://api.supermemory.ai/v3/documents" \
|
||||
-H "Authorization: Bearer $SUPERMEMORY_API_KEY" \
|
||||
-H "Content-Type: application/json" \
|
||||
-d '{"content": "# Project Documentation\n\n## Features\n- **Real-time sync**\n- **AI search**", "containerTag": "docs"}'
|
||||
```
|
||||
|
||||
</CodeGroup>
|
||||
|
|
@ -1,195 +0,0 @@
|
|||
---
|
||||
title: "File Upload"
|
||||
description: "Upload PDFs, images, and other files to Supermemory"
|
||||
---
|
||||
|
||||
Upload files directly to Supermemory for automatic content extraction and processing.
|
||||
|
||||
## Upload a PDF
|
||||
|
||||
Extract text from PDFs with OCR support.
|
||||
|
||||
<CodeGroup>
|
||||
|
||||
```typescript TypeScript
|
||||
const file = fs.createReadStream('document.pdf');
|
||||
|
||||
const response = await client.documents.uploadFile({
|
||||
file: file,
|
||||
containerTags: 'documents'
|
||||
});
|
||||
|
||||
console.log(response.id);
|
||||
// Output: pdf_123
|
||||
```
|
||||
|
||||
```python Python
|
||||
with open('document.pdf', 'rb') as file:
|
||||
response = client.documents.upload_file(
|
||||
file=file,
|
||||
container_tags='documents'
|
||||
)
|
||||
|
||||
print(response['id'])
|
||||
# Output: pdf_123
|
||||
```
|
||||
|
||||
```bash cURL
|
||||
curl -X POST "https://api.supermemory.ai/v3/documents/file" \
|
||||
-H "Authorization: Bearer $SUPERMEMORY_API_KEY" \
|
||||
-F "file=@document.pdf" \
|
||||
-F "containerTags=documents"
|
||||
|
||||
# Response: {"id": "pdf_123", "status": "processing"}
|
||||
```
|
||||
|
||||
</CodeGroup>
|
||||
|
||||
## Upload Images with OCR
|
||||
|
||||
Extract text from images.
|
||||
|
||||
<CodeGroup>
|
||||
|
||||
```typescript TypeScript
|
||||
const image = fs.createReadStream('screenshot.png');
|
||||
|
||||
await client.documents.uploadFile({
|
||||
file: image,
|
||||
containerTags: 'images'
|
||||
});
|
||||
```
|
||||
|
||||
```python Python
|
||||
with open('screenshot.png', 'rb') as file:
|
||||
client.documents.upload_file(
|
||||
file=file,
|
||||
container_tags='images'
|
||||
)
|
||||
```
|
||||
|
||||
```bash cURL
|
||||
curl -X POST "https://api.supermemory.ai/v3/documents/file" \
|
||||
-H "Authorization: Bearer $SUPERMEMORY_API_KEY" \
|
||||
-F "file=@screenshot.png" \
|
||||
-F "containerTags=images"
|
||||
```
|
||||
|
||||
</CodeGroup>
|
||||
|
||||
## Browser File Upload
|
||||
|
||||
Handle browser file uploads.
|
||||
|
||||
<CodeGroup>
|
||||
|
||||
```javascript JavaScript
|
||||
const formData = new FormData();
|
||||
formData.append('file', fileInput.files[0]);
|
||||
formData.append('containerTags', 'uploads');
|
||||
|
||||
const response = await fetch('https://api.supermemory.ai/v3/documents/file', {
|
||||
method: 'POST',
|
||||
headers: {
|
||||
'Authorization': `Bearer ${API_KEY}`
|
||||
},
|
||||
body: formData
|
||||
});
|
||||
|
||||
const result = await response.json();
|
||||
console.log(result.id);
|
||||
```
|
||||
|
||||
```typescript React
|
||||
function handleUpload(file: File) {
|
||||
const formData = new FormData();
|
||||
formData.append('file', file);
|
||||
formData.append('containerTags', 'uploads');
|
||||
|
||||
return fetch('https://api.supermemory.ai/v3/documents/file', {
|
||||
method: 'POST',
|
||||
headers: { 'Authorization': `Bearer ${API_KEY}` },
|
||||
body: formData
|
||||
});
|
||||
}
|
||||
```
|
||||
|
||||
```bash cURL
|
||||
# Browser uploads use FormData, same as file upload
|
||||
curl -X POST "https://api.supermemory.ai/v3/documents/file" \
|
||||
-H "Authorization: Bearer $SUPERMEMORY_API_KEY" \
|
||||
-F "file=@document.pdf" \
|
||||
-F "containerTags=uploads"
|
||||
```
|
||||
|
||||
</CodeGroup>
|
||||
|
||||
## Upload Multiple Files
|
||||
|
||||
Batch upload with rate limiting.
|
||||
|
||||
<CodeGroup>
|
||||
|
||||
```typescript TypeScript
|
||||
for (const file of files) {
|
||||
const stream = fs.createReadStream(file);
|
||||
|
||||
await client.documents.uploadFile({
|
||||
file: stream,
|
||||
containerTags: 'batch'
|
||||
});
|
||||
|
||||
// Rate limit
|
||||
await new Promise(r => setTimeout(r, 1000));
|
||||
}
|
||||
```
|
||||
|
||||
```python Python
|
||||
import time
|
||||
|
||||
for file_path in files:
|
||||
with open(file_path, 'rb') as file:
|
||||
client.documents.upload_file(
|
||||
file=file,
|
||||
container_tags='batch'
|
||||
)
|
||||
|
||||
time.sleep(1) # Rate limit
|
||||
```
|
||||
|
||||
```bash cURL
|
||||
# Upload each file separately with delays
|
||||
for file in *.pdf; do
|
||||
curl -X POST "https://api.supermemory.ai/v3/documents/file" \
|
||||
-H "Authorization: Bearer $SUPERMEMORY_API_KEY" \
|
||||
-F "file=@$file" \
|
||||
-F "containerTags=batch"
|
||||
|
||||
sleep 1 # Rate limit
|
||||
done
|
||||
```
|
||||
|
||||
</CodeGroup>
|
||||
|
||||
## Supported File Types
|
||||
|
||||
### Documents
|
||||
| Format | Extensions | Processing |
|
||||
|--------|------------|------------|
|
||||
| PDF | .pdf | Text extraction, OCR for scanned pages |
|
||||
| Microsoft Word | .doc, .docx | Full text and formatting extraction |
|
||||
| Plain Text | .txt, .md | Direct text processing |
|
||||
| CSV | .csv | Structured data extraction |
|
||||
|
||||
### Images
|
||||
| Format | Extensions | Processing |
|
||||
|--------|------------|------------|
|
||||
| JPEG | .jpg, .jpeg | OCR text extraction |
|
||||
| PNG | .png | OCR text extraction |
|
||||
| GIF | .gif | OCR for static images |
|
||||
| WebP | .webp | OCR text extraction |
|
||||
|
||||
### Size Limits
|
||||
- **Maximum file size**: 50MB
|
||||
- **Recommended size**: < 10MB for optimal processing
|
||||
- **Large files**: May take longer to process
|
||||
|
|
@ -1,249 +0,0 @@
|
|||
---
|
||||
title: "Add Memories Overview"
|
||||
description: "Add content to Supermemory through text, files, or URLs"
|
||||
sidebarTitle: "Overview"
|
||||
---
|
||||
|
||||
Add any type of content to Supermemory - text, files, URLs, images, videos, and more. Everything is automatically processed into searchable memories that form part of your intelligent knowledge graph.
|
||||
|
||||
## Prerequisites
|
||||
|
||||
Before adding memories, you need to set up the Supermemory client:
|
||||
|
||||
- **Install the SDK** for your language
|
||||
- **Get your API key** from [Supermemory Console](https://console.supermemory.ai)
|
||||
- **Initialize the client** with your API key
|
||||
|
||||
<CodeGroup>
|
||||
|
||||
```bash npm
|
||||
npm install supermemory
|
||||
```
|
||||
|
||||
```bash pip
|
||||
pip install supermemory
|
||||
```
|
||||
|
||||
</CodeGroup>
|
||||
|
||||
<CodeGroup>
|
||||
|
||||
```typescript TypeScript
|
||||
import Supermemory from 'supermemory';
|
||||
|
||||
const client = new Supermemory({
|
||||
apiKey: process.env.SUPERMEMORY_API_KEY!
|
||||
});
|
||||
```
|
||||
|
||||
```python Python
|
||||
from supermemory import Supermemory
|
||||
import os
|
||||
|
||||
client = Supermemory(
|
||||
api_key=os.environ.get("SUPERMEMORY_API_KEY")
|
||||
)
|
||||
```
|
||||
|
||||
</CodeGroup>
|
||||
|
||||
## Quick Start
|
||||
|
||||
<CodeGroup>
|
||||
|
||||
```typescript TypeScript
|
||||
// Add text content
|
||||
const result = await client.add({
|
||||
content: "Machine learning enables computers to learn from data",
|
||||
containerTag: "ai-research",
|
||||
metadata: { priority: "high" }
|
||||
});
|
||||
|
||||
console.log(result);
|
||||
// Output: { id: "abc123", status: "queued" }
|
||||
```
|
||||
|
||||
```python Python
|
||||
# Add text content
|
||||
result = client.add(
|
||||
content="Machine learning enables computers to learn from data",
|
||||
container_tags=["ai-research"],
|
||||
metadata={"priority": "high"}
|
||||
)
|
||||
|
||||
print(result)
|
||||
# Output: {"id": "abc123", "status": "queued"}
|
||||
```
|
||||
|
||||
```bash cURL
|
||||
curl -X POST "https://api.supermemory.ai/v3/documents" \
|
||||
-H "Authorization: Bearer $SUPERMEMORY_API_KEY" \
|
||||
-H "Content-Type: application/json" \
|
||||
-d '{
|
||||
"content": "Machine learning enables computers to learn from data",
|
||||
"containerTag": "ai-research",
|
||||
"metadata": {"priority": "high"}
|
||||
}'
|
||||
|
||||
# Response: {"id": "abc123", "status": "queued"}
|
||||
```
|
||||
|
||||
</CodeGroup>
|
||||
|
||||
## Key Concepts
|
||||
|
||||
<Note>
|
||||
**New to Supermemory?** Read [How Supermemory Works](/how-it-works) to understand the knowledge graph architecture and the distinction between documents and memories.
|
||||
</Note>
|
||||
|
||||
### Quick Overview
|
||||
- **Documents**: Raw content you upload (PDFs, URLs, text)
|
||||
- **Memories**: Searchable chunks created automatically with relationships
|
||||
- **Container Tags**: Group related content for better context
|
||||
- **Metadata**: Additional information for filtering
|
||||
|
||||
### Content Sources
|
||||
|
||||
Add content through three methods:
|
||||
|
||||
1. **Direct Text**: Send text content directly via API
|
||||
2. **File Upload**: Upload PDFs, images, videos for extraction
|
||||
3. **URL Processing**: Automatic extraction from web pages and platforms
|
||||
|
||||
## Endpoints
|
||||
|
||||
<Warning>
|
||||
Remember, these endpoints add documents. Memories are inferred by Supermemory.
|
||||
</Warning>
|
||||
|
||||
### Add Content
|
||||
|
||||
`POST /v3/documents`
|
||||
|
||||
Add text content, URLs, or any supported format.
|
||||
|
||||
<CodeGroup>
|
||||
|
||||
```typescript TypeScript
|
||||
await client.add({
|
||||
content: "Your content here",
|
||||
containerTag: "project"
|
||||
});
|
||||
```
|
||||
|
||||
```python Python
|
||||
client.add(
|
||||
content="Your content here",
|
||||
container_tags=["project"]
|
||||
)
|
||||
```
|
||||
|
||||
```bash cURL
|
||||
curl -X POST "https://api.supermemory.ai/v3/documents" \
|
||||
-H "Authorization: Bearer $SUPERMEMORY_API_KEY" \
|
||||
-H "Content-Type: application/json" \
|
||||
-d '{"content": "Your content here", "containerTag": "project"}'
|
||||
```
|
||||
|
||||
</CodeGroup>
|
||||
|
||||
### Upload File
|
||||
|
||||
`POST /v3/documents/file`
|
||||
|
||||
Upload files directly for processing.
|
||||
|
||||
<CodeGroup>
|
||||
|
||||
```typescript TypeScript
|
||||
await client.documents.uploadFile({
|
||||
file: fileStream,
|
||||
containerTag: "project"
|
||||
});
|
||||
```
|
||||
|
||||
```python Python
|
||||
client.documents.upload_file(
|
||||
file=open('file.pdf', 'rb'),
|
||||
container_tags='project'
|
||||
)
|
||||
```
|
||||
|
||||
```bash cURL
|
||||
curl -X POST "https://api.supermemory.ai/v3/documents/file" \
|
||||
-H "Authorization: Bearer $SUPERMEMORY_API_KEY" \
|
||||
-F "file=@document.pdf" \
|
||||
-F "containerTags=project"
|
||||
```
|
||||
|
||||
</CodeGroup>
|
||||
|
||||
### Update Memory
|
||||
|
||||
`PATCH /v3/documents/{id}`
|
||||
|
||||
Update existing document content or metadata. Content changes trigger reindexing; metadata-only updates do not.
|
||||
|
||||
<CodeGroup>
|
||||
|
||||
```typescript TypeScript
|
||||
await client.documents.update("doc_id", {
|
||||
content: "Updated content"
|
||||
});
|
||||
```
|
||||
|
||||
```python Python
|
||||
client.documents.update("doc_id", {
|
||||
"content": "Updated content"
|
||||
})
|
||||
```
|
||||
|
||||
```bash cURL
|
||||
curl -X PATCH "https://api.supermemory.ai/v3/documents/doc_id" \
|
||||
-H "Authorization: Bearer $SUPERMEMORY_API_KEY" \
|
||||
-H "Content-Type: application/json" \
|
||||
-d '{"content": "Updated content"}'
|
||||
```
|
||||
|
||||
</CodeGroup>
|
||||
|
||||
## Supported Content Types
|
||||
|
||||
### Documents
|
||||
- PDF with OCR support
|
||||
- Google Docs, Sheets, Slides
|
||||
- Notion pages
|
||||
- Microsoft Office files
|
||||
|
||||
### Media
|
||||
- Images (JPG, PNG, GIF, WebP) with OCR
|
||||
|
||||
### Web Content
|
||||
- Twitter/X posts
|
||||
- YouTube videos with captions
|
||||
|
||||
### Text Formats
|
||||
- Plain text
|
||||
- Markdown
|
||||
- CSV files
|
||||
|
||||
<Note> Refer to the [connectors guide](/connectors/overview) to learn how you can connect Google Drive, Notion, and OneDrive and sync files in real-time. </Note>
|
||||
|
||||
## Response Format
|
||||
|
||||
```json
|
||||
{
|
||||
"id": "D2Ar7Vo7ub83w3PRPZcaP1",
|
||||
"status": "queued"
|
||||
}
|
||||
```
|
||||
|
||||
- **`id`**: Unique document identifier
|
||||
- **`status`**: Processing state (`queued`, `processing`, `done`)
|
||||
|
||||
|
||||
|
||||
## Next Steps
|
||||
|
||||
- [Memory Operations](/memory-operations) - Track status, list, update, and delete memories
|
||||
- [Search Memories](/search) - Search your content
|
||||
|
|
@ -1,156 +0,0 @@
|
|||
---
|
||||
title: "Parameters"
|
||||
description: "Complete reference for add memory parameters"
|
||||
---
|
||||
|
||||
Detailed parameter documentation for adding memories to Supermemory.
|
||||
|
||||
## Request Parameters
|
||||
|
||||
### Required Parameters
|
||||
|
||||
<ParamField body="content" type="string" required>
|
||||
The content to process into memories. Can be:
|
||||
- Plain text content
|
||||
- URL to process
|
||||
- HTML content
|
||||
- Markdown text
|
||||
|
||||
```json
|
||||
{
|
||||
"content": "Machine learning is a subset of AI..."
|
||||
}
|
||||
```
|
||||
|
||||
**URL Examples:**
|
||||
```json
|
||||
{
|
||||
"content": "https://youtube.com/watch?v=dQw4w9WgXcQ"
|
||||
}
|
||||
```
|
||||
</ParamField>
|
||||
|
||||
### Optional Parameters
|
||||
|
||||
<ParamField body="containerTag" type="string">
|
||||
**Recommended.** Single tag to group related memories. Improves search performance.
|
||||
|
||||
Default: `"sm_project_default"`
|
||||
|
||||
```json
|
||||
{
|
||||
"containerTag": "project_alpha"
|
||||
}
|
||||
```
|
||||
|
||||
<Note>
|
||||
Use `containerTag` (singular) for better performance than `containerTags` (array).
|
||||
</Note>
|
||||
</ParamField>
|
||||
|
||||
<ParamField body="metadata" type="object">
|
||||
Additional metadata as key-value pairs. Values must be strings, numbers, or booleans.
|
||||
|
||||
```json
|
||||
{
|
||||
"metadata": {
|
||||
"source": "research-paper",
|
||||
"author": "John Doe",
|
||||
"priority": 1,
|
||||
"reviewed": true
|
||||
}
|
||||
}
|
||||
```
|
||||
|
||||
**Restrictions:**
|
||||
- No nested objects
|
||||
- No arrays as values
|
||||
- Keys must be strings
|
||||
- Values: string, number, or boolean only
|
||||
</ParamField>
|
||||
|
||||
<ParamField body="customId" type="string">
|
||||
Your own identifier for the document. Enables deduplication and updates.
|
||||
|
||||
**Maximum length:** 255 characters
|
||||
|
||||
```json
|
||||
{
|
||||
"customId": "doc_2024_01_research_ml"
|
||||
}
|
||||
```
|
||||
|
||||
**Use cases:**
|
||||
- Prevent duplicate uploads
|
||||
- Update existing documents
|
||||
- Sync with external systems
|
||||
</ParamField>
|
||||
|
||||
<ParamField body="raw" type="string">
|
||||
Raw content to store alongside processed content. Useful for preserving original formatting.
|
||||
|
||||
```json
|
||||
{
|
||||
"content": "# Machine Learning\n\nML is a subset of AI...",
|
||||
"raw": "# Machine Learning\n\nML is a subset of AI..."
|
||||
}
|
||||
```
|
||||
</ParamField>
|
||||
|
||||
## File Upload Parameters
|
||||
|
||||
For `POST /v3/documents/file` endpoint:
|
||||
|
||||
<ParamField body="file" type="file" required>
|
||||
The file to upload. Supported formats:
|
||||
- **Documents:** PDF, DOC, DOCX, TXT, MD
|
||||
- **Images:** JPG, PNG, GIF, WebP
|
||||
- **Videos:** MP4, WebM, AVI
|
||||
|
||||
**Maximum size:** 50MB
|
||||
</ParamField>
|
||||
|
||||
<ParamField body="containerTags" type="string">
|
||||
Container tag for the uploaded file (sent as form field).
|
||||
|
||||
```bash
|
||||
curl -X POST "https://api.supermemory.ai/v3/documents/file" \
|
||||
-F "file=@document.pdf" \
|
||||
-F "containerTags=research"
|
||||
```
|
||||
</ParamField>
|
||||
|
||||
|
||||
## Container Tag Patterns
|
||||
|
||||
### Recommended Patterns
|
||||
|
||||
```typescript
|
||||
// By user
|
||||
"user_123"
|
||||
|
||||
// By project
|
||||
"project_alpha"
|
||||
|
||||
// By organization and type
|
||||
"org_456_research"
|
||||
|
||||
// By time period
|
||||
"2024_q1_reports"
|
||||
|
||||
// By data source
|
||||
"slack_channel_general"
|
||||
```
|
||||
|
||||
### Performance Considerations
|
||||
|
||||
```typescript
|
||||
// ✅ FAST: Single tag
|
||||
{ "containerTag": "project_alpha" }
|
||||
|
||||
// ⚠️ SLOWER: Multiple tags
|
||||
{ "containerTags": ["project_alpha", "backend", "auth"] }
|
||||
|
||||
// ❌ AVOID: Too many tags
|
||||
{ "containerTags": ["tag1", "tag2", "tag3", "tag4", "tag5"] }
|
||||
```
|
||||
|
|
@ -1,216 +0,0 @@
|
|||
---
|
||||
title: "Infinite Chat"
|
||||
description: "Unlimited context for chat applications with automatic memory management"
|
||||
sidebarTitle: "Infinite Chat"
|
||||
---
|
||||
|
||||
Infinite Chat provides unlimited context for chat applications with automatic memory management.
|
||||
|
||||
## Setup
|
||||
|
||||
```typescript
|
||||
import { streamText } from "ai"
|
||||
|
||||
const infiniteChat = createAnthropic({
|
||||
baseUrl: 'https://api.supermemory.ai/v3/https://api.anthropic.com/v1',
|
||||
apiKey: 'your-provider-api-key',
|
||||
headers: {
|
||||
'x-supermemory-api-key': 'supermemory-api-key',
|
||||
'x-sm-conversation-id': 'conversation-id'
|
||||
}
|
||||
})
|
||||
|
||||
const result = await streamText({
|
||||
model: infiniteChat("claude-3-sonnet"),
|
||||
messages: [
|
||||
{ role: "user", content: "Hello! Remember that I love TypeScript." }
|
||||
]
|
||||
})
|
||||
```
|
||||
|
||||
## Provider Configuration
|
||||
|
||||
### Named Providers
|
||||
|
||||
<CodeGroup>
|
||||
|
||||
```typescript OpenAI
|
||||
const infiniteChat = createOpenAI({
|
||||
baseUrl: 'https://api.supermemory.ai/v3/https://api.openai.com/v1',
|
||||
apiKey: 'your-provider-api-key',
|
||||
headers: {
|
||||
'x-supermemory-api-key': 'supermemory-api-key',
|
||||
'x-sm-conversation-id': 'conversation-id'
|
||||
}
|
||||
})
|
||||
|
||||
const result = await streamText({
|
||||
model: infiniteChat("gpt-5"),
|
||||
messages: [...]
|
||||
})
|
||||
```
|
||||
|
||||
```typescript Anthropic
|
||||
const infiniteChat = createAnthropic({
|
||||
baseUrl: 'https://api.supermemory.ai/v3/https://api.anthropic.com/v1',
|
||||
apiKey: 'your-provider-api-key',
|
||||
headers: {
|
||||
'x-supermemory-api-key': 'supermemory-api-key',
|
||||
'x-sm-conversation-id': 'conversation-id'
|
||||
}
|
||||
})
|
||||
|
||||
const result = await streamText({
|
||||
model: infiniteChat("claude-3-sonnet"),
|
||||
messages: [...]
|
||||
})
|
||||
```
|
||||
|
||||
```typescript Google
|
||||
const infiniteChat = createGoogleGenerativeAI({
|
||||
baseUrl: 'https://api.supermemory.ai/v3/https://generativelanguage.googleapis.com/v1beta',
|
||||
apiKey: 'your-provider-api-key',
|
||||
headers: {
|
||||
'x-supermemory-api-key': 'supermemory-api-key',
|
||||
'x-sm-conversation-id': 'conversation-id'
|
||||
}
|
||||
})
|
||||
|
||||
const result = await streamText({
|
||||
model: infiniteChat("gemini-pro"),
|
||||
messages: [...]
|
||||
})
|
||||
```
|
||||
|
||||
```typescript Groq
|
||||
const infiniteChat = createGroq({
|
||||
baseUrl: 'https://api.supermemory.ai/v3/https://api.groq.com/v1',
|
||||
apiKey: 'your-provider-api-key',
|
||||
headers: {
|
||||
'x-supermemory-api-key': 'supermemory-api-key',
|
||||
'x-sm-conversation-id': 'conversation-id'
|
||||
}
|
||||
})
|
||||
|
||||
const result = await streamText({
|
||||
model: infiniteChat("mixtral-8x7b"),
|
||||
messages: [...]
|
||||
})
|
||||
```
|
||||
|
||||
</CodeGroup>
|
||||
|
||||
### Custom Provider URL
|
||||
|
||||
```typescript
|
||||
const infiniteChat = createOpenAI({
|
||||
baseUrl: 'https://api.supermemory.ai/v3/https://api.openai.com/v1',
|
||||
apiKey: 'your-provider-api-key',
|
||||
headers: {
|
||||
'x-supermemory-api-key': 'supermemory-api-key',
|
||||
'x-sm-conversation-id': 'conversation-id'
|
||||
}
|
||||
})
|
||||
```
|
||||
|
||||
## Example Usage
|
||||
|
||||
```typescript
|
||||
import { streamText } from "ai"
|
||||
|
||||
const infiniteChat = createOpenAI({
|
||||
baseUrl: 'https://api.supermemory.ai/v3/https://api.openai.com/v1',
|
||||
apiKey: 'your-provider-api-key',
|
||||
headers: {
|
||||
'x-supermemory-api-key': 'supermemory-api-key',
|
||||
'x-sm-conversation-id': 'conversation-id'
|
||||
}
|
||||
})
|
||||
|
||||
const result = await streamText({
|
||||
model: infiniteChat("gpt-5"),
|
||||
messages: [
|
||||
{ role: "user", content: "What did we discuss yesterday?" }
|
||||
]
|
||||
})
|
||||
|
||||
return result.toAIStreamResponse()
|
||||
```
|
||||
|
||||
## Configuration Options
|
||||
|
||||
```typescript
|
||||
interface ConfigWithProviderName {
|
||||
providerName: 'openai' | 'anthropic' | 'openrouter' |
|
||||
'deepinfra' | 'groq' | 'google' | 'cloudflare'
|
||||
providerApiKey: string
|
||||
headers?: Record<string, string>
|
||||
}
|
||||
|
||||
interface ConfigWithProviderUrl {
|
||||
providerUrl: string
|
||||
providerApiKey: string
|
||||
headers?: Record<string, string>
|
||||
}
|
||||
```
|
||||
|
||||
### Custom Headers
|
||||
|
||||
Add user IDs, conversation IDs, or other metadata:
|
||||
|
||||
```typescript
|
||||
const infiniteChat = createOpenAI({
|
||||
baseUrl: 'https://api.supermemory.ai/v3/https://api.openai.com/v1',
|
||||
apiKey: 'your-provider-api-key',
|
||||
headers: {
|
||||
'x-supermemory-api-key': 'supermemory-api-key',
|
||||
'x-sm-conversation-id': 'conversation-id'
|
||||
}
|
||||
})
|
||||
```
|
||||
|
||||
## Comparison with Memory Tools
|
||||
|
||||
| Feature | Infinite Chat | Memory Tools |
|
||||
|---------|--------------|--------------|
|
||||
| Memory Management | Automatic | Manual |
|
||||
| Context Handling | Automatic | Manual |
|
||||
| Tool Calls | None | searchMemories, addMemory, fetchMemory |
|
||||
| Best For | Chat apps | AI agents |
|
||||
| Setup Complexity | Simple | Moderate |
|
||||
|
||||
## Headers
|
||||
|
||||
Add user and conversation context:
|
||||
|
||||
```typescript
|
||||
const infiniteChat = createOpenAI({
|
||||
baseUrl: 'https://api.supermemory.ai/v3/https://api.openai.com/v1',
|
||||
apiKey: 'your-provider-api-key',
|
||||
headers: {
|
||||
'x-supermemory-api-key': 'supermemory-api-key',
|
||||
'x-sm-conversation-id': 'conversation-id'
|
||||
}
|
||||
})
|
||||
```
|
||||
|
||||
## Comparison
|
||||
|
||||
| Feature | Infinite Chat | Memory Tools |
|
||||
|---------|--------------|-------------|
|
||||
| Memory Management | Automatic | Manual |
|
||||
| Context Handling | Automatic | Manual |
|
||||
| Tool Calls | None | searchMemories, addMemory, fetchMemory |
|
||||
| Best For | Chat apps | AI agents |
|
||||
|
||||
## Next Steps
|
||||
|
||||
<CardGroup cols={2}>
|
||||
<Card title="Memory Tools" icon="wrench" href="/integrations/ai-sdk">
|
||||
Explore explicit memory control
|
||||
</Card>
|
||||
|
||||
<Card title="Examples" icon="code" href="/cookbook/ai-sdk-integration">
|
||||
See complete implementations
|
||||
</Card>
|
||||
</CardGroup>
|
||||
|
|
@ -1,147 +0,0 @@
|
|||
---
|
||||
title: "Memory Tools"
|
||||
description: "Add memory capabilities to your AI agents with Vercel AI SDK tools"
|
||||
sidebarTitle: "Memory Tools"
|
||||
---
|
||||
|
||||
Memory tools allow AI agents to search, add, and fetch memories.
|
||||
|
||||
## Setup
|
||||
|
||||
```typescript
|
||||
import { streamText } from "ai"
|
||||
import { createOpenAI } from "@ai-sdk/openai"
|
||||
import { supermemoryTools } from "@supermemory/tools/ai-sdk"
|
||||
|
||||
const openai = createOpenAI({
|
||||
apiKey: "YOUR_OPENAI_KEY"
|
||||
})
|
||||
|
||||
const result = await streamText({
|
||||
model: openai("gpt-5"),
|
||||
prompt: "Remember that my name is Alice",
|
||||
tools: supermemoryTools("YOUR_SUPERMEMORY_KEY")
|
||||
})
|
||||
```
|
||||
|
||||
## Available Tools
|
||||
|
||||
### Search Memories
|
||||
|
||||
Semantic search through user memories:
|
||||
|
||||
```typescript
|
||||
const result = await streamText({
|
||||
model: openai("gpt-5"),
|
||||
prompt: "What are my dietary preferences?",
|
||||
tools: supermemoryTools("API_KEY")
|
||||
})
|
||||
|
||||
// The AI will automatically call searchMemories tool
|
||||
// Example tool call:
|
||||
// searchMemories({ informationToGet: "dietary preferences and restrictions" })
|
||||
```
|
||||
|
||||
### Add Memory
|
||||
|
||||
Store new information:
|
||||
|
||||
```typescript
|
||||
const result = await streamText({
|
||||
model: anthropic("claude-3-sonnet"),
|
||||
prompt: "Remember that I'm allergic to peanuts",
|
||||
tools: supermemoryTools("API_KEY")
|
||||
})
|
||||
|
||||
// The AI will automatically call addMemory tool
|
||||
// Example tool call:
|
||||
// addMemory({ memory: "User is allergic to peanuts" })
|
||||
```
|
||||
|
||||
### Fetch Memory
|
||||
|
||||
Retrieve specific memory by ID:
|
||||
|
||||
```typescript
|
||||
const result = await streamText({
|
||||
model: openai("gpt-5"),
|
||||
prompt: "Get the details of memory abc123",
|
||||
tools: supermemoryTools("API_KEY")
|
||||
})
|
||||
|
||||
// The AI will automatically call fetchMemory tool
|
||||
// Example tool call:
|
||||
// fetchMemory({ memoryId: "abc123" })
|
||||
```
|
||||
|
||||
## Using Individual Tools
|
||||
|
||||
For more control, import tools separately:
|
||||
|
||||
```typescript
|
||||
import {
|
||||
searchMemoriesTool,
|
||||
addMemoryTool,
|
||||
fetchMemoryTool
|
||||
} from "@supermemory/tools/ai-sdk"
|
||||
|
||||
// Use only search tool
|
||||
const result = await streamText({
|
||||
model: openai("gpt-5"),
|
||||
prompt: "What do you know about me?",
|
||||
tools: {
|
||||
searchMemories: searchMemoriesTool("API_KEY", {
|
||||
projectId: "personal"
|
||||
})
|
||||
}
|
||||
})
|
||||
|
||||
// Combine with custom tools
|
||||
const result = await streamText({
|
||||
model: anthropic("claude-3"),
|
||||
prompt: "Help me with my calendar",
|
||||
tools: {
|
||||
searchMemories: searchMemoriesTool("API_KEY"),
|
||||
// Your custom tools
|
||||
createEvent: yourCustomTool,
|
||||
sendEmail: anotherCustomTool
|
||||
}
|
||||
})
|
||||
```
|
||||
|
||||
## Tool Results
|
||||
|
||||
Each tool returns a result object:
|
||||
|
||||
```typescript
|
||||
// searchMemories result
|
||||
{
|
||||
success: true,
|
||||
results: [...], // Array of memories
|
||||
count: 5
|
||||
}
|
||||
|
||||
// addMemory result
|
||||
{
|
||||
success: true,
|
||||
memory: { id: "mem_123", ... }
|
||||
}
|
||||
|
||||
// fetchMemory result
|
||||
{
|
||||
success: true,
|
||||
memory: { id: "mem_123", content: "...", ... }
|
||||
}
|
||||
```
|
||||
|
||||
## Next Steps
|
||||
|
||||
<CardGroup cols={2}>
|
||||
<Card title="User Profiles" icon="user" href="/integrations/ai-sdk">
|
||||
Automatic personalization with profiles
|
||||
</Card>
|
||||
|
||||
<Card title="Examples" icon="code" href="/cookbook/ai-sdk-integration">
|
||||
See more complete examples
|
||||
</Card>
|
||||
</CardGroup>
|
||||
|
|
@ -1,93 +0,0 @@
|
|||
---
|
||||
title: "AI SDK Integration"
|
||||
description: "Use Supermemory with Vercel AI SDK for seamless memory management"
|
||||
sidebarTitle: "Overview"
|
||||
---
|
||||
|
||||
The Supermemory AI SDK provides native integration with Vercel's AI SDK through two approaches: **User Profiles** for automatic personalization and **Memory Tools** for agent-based interactions.
|
||||
|
||||
<Card title="Supermemory tools on npm" icon="npm" href="https://www.npmjs.com/package/@supermemory/tools">
|
||||
Check out the NPM page for more details
|
||||
</Card>
|
||||
|
||||
## Installation
|
||||
|
||||
```bash
|
||||
npm install @supermemory/tools
|
||||
```
|
||||
|
||||
## User Profiles with Middleware
|
||||
|
||||
Automatically inject user profiles into every LLM call for instant personalization. Customize how memories are formatted with the `promptTemplate` option for XML-based prompting, custom branding, or model-specific formatting.
|
||||
|
||||
```typescript
|
||||
import { generateText } from "ai"
|
||||
import { withSupermemory } from "@supermemory/tools/ai-sdk"
|
||||
import { openai } from "@ai-sdk/openai"
|
||||
|
||||
// Wrap your model with Supermemory - profiles are automatically injected
|
||||
const modelWithMemory = withSupermemory(openai("gpt-5"), {
|
||||
containerTag: "user-123",
|
||||
customId: "conversation-456",
|
||||
})
|
||||
|
||||
const result = await generateText({
|
||||
model: modelWithMemory,
|
||||
messages: [{ role: "user", content: "What do you know about me?" }]
|
||||
})
|
||||
// The model automatically has the user's profile context!
|
||||
```
|
||||
|
||||
<Note>
|
||||
**Memory saving is enabled by default** (`addMemory: "always"`). New conversations are persisted automatically. To opt out, set `addMemory: "never"`:
|
||||
|
||||
```typescript
|
||||
const modelWithMemory = withSupermemory(openai("gpt-5"), {
|
||||
containerTag: "user-123",
|
||||
customId: "conversation-456",
|
||||
addMemory: "never",
|
||||
})
|
||||
```
|
||||
</Note>
|
||||
|
||||
```typescript
|
||||
```
|
||||
|
||||
## Memory Tools
|
||||
|
||||
Add memory capabilities to AI agents with search, add, and fetch operations.
|
||||
|
||||
```typescript
|
||||
import { streamText } from "ai"
|
||||
import { createAnthropic } from "@ai-sdk/anthropic"
|
||||
import { supermemoryTools } from "@supermemory/tools/ai-sdk"
|
||||
|
||||
const anthropic = createAnthropic({
|
||||
apiKey: "YOUR_ANTHROPIC_KEY"
|
||||
})
|
||||
|
||||
const result = await streamText({
|
||||
model: anthropic("claude-3-sonnet"),
|
||||
prompt: "Remember that my name is Alice",
|
||||
tools: supermemoryTools("YOUR_SUPERMEMORY_KEY")
|
||||
})
|
||||
```
|
||||
|
||||
## When to Use
|
||||
|
||||
| Approach | Use Case |
|
||||
|----------|----------|
|
||||
| User Profiles | Personalized LLM responses with automatic user context |
|
||||
| Memory Tools | AI agents that need explicit memory control |
|
||||
|
||||
## Next Steps
|
||||
|
||||
<CardGroup cols={2}>
|
||||
<Card title="User Profiles" icon="user" href="/integrations/ai-sdk">
|
||||
Automatic personalization with profiles
|
||||
</Card>
|
||||
|
||||
<Card title="Memory Tools" icon="wrench" href="/integrations/ai-sdk">
|
||||
Agent-based memory management
|
||||
</Card>
|
||||
</CardGroup>
|
||||
|
|
@ -1,357 +0,0 @@
|
|||
---
|
||||
title: "User Profiles with AI SDK"
|
||||
description: "Automatically inject user profiles into LLM calls for instant personalization"
|
||||
sidebarTitle: "User Profiles"
|
||||
---
|
||||
|
||||
## Overview
|
||||
|
||||
The `withSupermemory` middleware automatically injects user profiles into your LLM calls, providing instant personalization without manual prompt engineering or API calls.
|
||||
|
||||
<Note>
|
||||
**New to User Profiles?** Read the [conceptual overview](/user-profiles) to understand what profiles are and why they're powerful for LLM personalization.
|
||||
</Note>
|
||||
|
||||
## Quick Start
|
||||
|
||||
```typescript
|
||||
import { generateText } from "ai"
|
||||
import { withSupermemory } from "@supermemory/tools/ai-sdk"
|
||||
import { openai } from "@ai-sdk/openai"
|
||||
|
||||
// Wrap any model with Supermemory middleware
|
||||
const modelWithMemory = withSupermemory(openai("gpt-4"), {
|
||||
containerTag: "user-123",
|
||||
customId: "conversation-456",
|
||||
})
|
||||
|
||||
// Use normally - profiles are automatically injected!
|
||||
const result = await generateText({
|
||||
model: modelWithMemory,
|
||||
messages: [{ role: "user", content: "Help me with my current project" }]
|
||||
})
|
||||
|
||||
// The model knows about the user's background, skills, and current work!
|
||||
```
|
||||
|
||||
## How It Works
|
||||
|
||||
The `withSupermemory` middleware:
|
||||
|
||||
1. **Intercepts** your LLM calls before they reach the model
|
||||
2. **Fetches** the user's profile based on the container tag
|
||||
3. **Injects** profile data into the system prompt automatically
|
||||
4. **Forwards** the enhanced prompt to your LLM
|
||||
|
||||
All of this happens transparently - you write code as if using a normal model, but get personalized responses.
|
||||
|
||||
<Note>
|
||||
**Memory saving is enabled by default** (`addMemory: "always"`). New conversations are persisted automatically. To opt out, set `addMemory: "never"`:
|
||||
|
||||
```typescript
|
||||
const model = withSupermemory(openai("gpt-5"), {
|
||||
containerTag: "user-123",
|
||||
customId: "conversation-456",
|
||||
addMemory: "never",
|
||||
})
|
||||
```
|
||||
</Note>
|
||||
|
||||
## Memory Search Modes
|
||||
|
||||
Configure how the middleware retrieves and uses memory:
|
||||
|
||||
### Profile Mode (Default)
|
||||
|
||||
Retrieves the user's complete profile without query-specific search. Best for general personalization.
|
||||
|
||||
```typescript
|
||||
// Default behavior - profile mode
|
||||
const model = withSupermemory(openai("gpt-4"), {
|
||||
containerTag: "user-123",
|
||||
customId: "conv-1",
|
||||
})
|
||||
|
||||
// Or explicitly specify
|
||||
const model = withSupermemory(openai("gpt-4"), {
|
||||
containerTag: "user-123",
|
||||
customId: "conv-1",
|
||||
mode: "profile",
|
||||
})
|
||||
|
||||
const result = await generateText({
|
||||
model,
|
||||
messages: [{ role: "user", content: "What do you know about me?" }]
|
||||
})
|
||||
// Response uses full user profile for context
|
||||
```
|
||||
|
||||
### Query Mode
|
||||
|
||||
Searches memories based on the user's specific message. Best for finding relevant information.
|
||||
|
||||
```typescript
|
||||
const model = withSupermemory(openai("gpt-4"), {
|
||||
containerTag: "user-123",
|
||||
customId: "conv-1",
|
||||
mode: "query",
|
||||
})
|
||||
|
||||
const result = await generateText({
|
||||
model,
|
||||
messages: [{
|
||||
role: "user",
|
||||
content: "What was that Python script I wrote last week?"
|
||||
}]
|
||||
})
|
||||
// Searches for memories about Python scripts from last week
|
||||
```
|
||||
|
||||
### Full Mode
|
||||
|
||||
Combines profile AND query-based search for comprehensive context. Best for complex interactions.
|
||||
|
||||
```typescript
|
||||
const model = withSupermemory(openai("gpt-4"), {
|
||||
containerTag: "user-123",
|
||||
customId: "conv-1",
|
||||
mode: "full",
|
||||
})
|
||||
|
||||
const result = await generateText({
|
||||
model,
|
||||
messages: [{
|
||||
role: "user",
|
||||
content: "Help me debug this similar to what we did before"
|
||||
}]
|
||||
})
|
||||
// Uses both profile (user's expertise) AND search (previous debugging sessions)
|
||||
```
|
||||
|
||||
## Custom Prompt Templates
|
||||
|
||||
Customize how memories are formatted and injected into the system prompt using the `promptTemplate` option. This is useful for:
|
||||
- Using XML-based prompting (e.g., for Claude models)
|
||||
- Custom branding (removing "supermemories" references)
|
||||
- Controlling how your agent describes where information comes from
|
||||
|
||||
```typescript
|
||||
import { generateText } from "ai"
|
||||
import { withSupermemory, type MemoryPromptData } from "@supermemory/tools/ai-sdk"
|
||||
import { openai } from "@ai-sdk/openai"
|
||||
|
||||
const customPrompt = (data: MemoryPromptData) => `
|
||||
<user_memories>
|
||||
Here is some information about your past conversations with the user:
|
||||
${data.userMemories}
|
||||
${data.generalSearchMemories}
|
||||
</user_memories>
|
||||
`.trim()
|
||||
|
||||
const model = withSupermemory(openai("gpt-4"), {
|
||||
containerTag: "user-123",
|
||||
customId: "conv-1",
|
||||
mode: "full",
|
||||
promptTemplate: customPrompt,
|
||||
})
|
||||
|
||||
const result = await generateText({
|
||||
model,
|
||||
messages: [{ role: "user", content: "What do you know about me?" }]
|
||||
})
|
||||
```
|
||||
|
||||
### MemoryPromptData Interface
|
||||
|
||||
The `MemoryPromptData` object passed to your template function provides:
|
||||
|
||||
- `userMemories`: Pre-formatted markdown combining static profile facts (name, preferences, goals) and dynamic context (current projects, recent interests)
|
||||
- `generalSearchMemories`: Pre-formatted search results based on semantic similarity to the current query (empty string if mode is "profile")
|
||||
- `searchResults`: Raw search results array (`Array<{ memory: string; metadata?: Record<string, unknown> }>`) for traversing, filtering, or selectively including results based on metadata
|
||||
|
||||
### XML-Based Prompting for Claude
|
||||
|
||||
Claude models perform better with XML-structured prompts:
|
||||
|
||||
```typescript
|
||||
const claudePrompt = (data: MemoryPromptData) => `
|
||||
<context>
|
||||
<user_profile>
|
||||
${data.userMemories}
|
||||
</user_profile>
|
||||
<relevant_memories>
|
||||
${data.generalSearchMemories}
|
||||
</relevant_memories>
|
||||
</context>
|
||||
|
||||
Use the above context to provide personalized responses.
|
||||
`.trim()
|
||||
|
||||
const model = withSupermemory(anthropic("claude-3-sonnet"), {
|
||||
containerTag: "user-123",
|
||||
customId: "conv-1",
|
||||
mode: "full",
|
||||
promptTemplate: claudePrompt,
|
||||
})
|
||||
```
|
||||
|
||||
### Filtering Search Results
|
||||
|
||||
Use `searchResults` to traverse the raw data and pick what's important:
|
||||
|
||||
```typescript
|
||||
const selectivePrompt = (data: MemoryPromptData) => {
|
||||
const relevant = data.searchResults.filter(
|
||||
(r) => (r.metadata?.score as number) > 0.7
|
||||
)
|
||||
return `
|
||||
<user_memories>
|
||||
${data.userMemories}
|
||||
</user_memories>
|
||||
<relevant_context>
|
||||
${relevant.map((r) => `- ${r.memory}`).join("\n")}
|
||||
</relevant_context>
|
||||
`.trim()
|
||||
}
|
||||
|
||||
const model = withSupermemory(openai("gpt-4"), {
|
||||
containerTag: "user-123",
|
||||
customId: "conv-1",
|
||||
mode: "full",
|
||||
promptTemplate: selectivePrompt,
|
||||
})
|
||||
```
|
||||
|
||||
### Custom Branding
|
||||
|
||||
Remove "supermemories" references and use your own branding:
|
||||
|
||||
```typescript
|
||||
const brandedPrompt = (data: MemoryPromptData) => `
|
||||
You are an AI assistant with access to the user's personal knowledge base.
|
||||
|
||||
User Profile:
|
||||
${data.userMemories}
|
||||
|
||||
Relevant Context:
|
||||
${data.generalSearchMemories}
|
||||
|
||||
Use this information to provide personalized and contextually relevant responses.
|
||||
`.trim()
|
||||
|
||||
const model = withSupermemory(openai("gpt-4"), {
|
||||
containerTag: "user-123",
|
||||
customId: "conv-1",
|
||||
promptTemplate: brandedPrompt,
|
||||
})
|
||||
```
|
||||
|
||||
### Default Template
|
||||
|
||||
If no `promptTemplate` is provided, the default format is used:
|
||||
|
||||
```typescript
|
||||
const defaultPrompt = (data: MemoryPromptData) =>
|
||||
`User Supermemories: \n${data.userMemories}\n${data.generalSearchMemories}`.trim()
|
||||
```
|
||||
|
||||
## Verbose Logging
|
||||
|
||||
Enable detailed logging to see exactly what's happening:
|
||||
|
||||
```typescript
|
||||
const model = withSupermemory(openai("gpt-4"), {
|
||||
containerTag: "user-123",
|
||||
customId: "conv-1",
|
||||
verbose: true, // Enable detailed logging
|
||||
})
|
||||
|
||||
const result = await generateText({
|
||||
model,
|
||||
messages: [{ role: "user", content: "Where do I live?" }]
|
||||
})
|
||||
|
||||
// Console output:
|
||||
// [supermemory] Searching memories for container: user-123
|
||||
// [supermemory] User message: Where do I live?
|
||||
// [supermemory] System prompt exists: false
|
||||
// [supermemory] Found 3 memories
|
||||
// [supermemory] Memory content: You live in San Francisco, California...
|
||||
// [supermemory] Creating new system prompt with memories
|
||||
```
|
||||
|
||||
## Comparison with Direct API
|
||||
|
||||
The AI SDK middleware abstracts away the complexity of manual profile management:
|
||||
|
||||
<Tabs>
|
||||
<Tab title="With AI SDK (Simple)">
|
||||
```typescript
|
||||
// Simple setup
|
||||
const model = withSupermemory(openai("gpt-4"), {
|
||||
containerTag: "user-123",
|
||||
customId: "conv-1",
|
||||
})
|
||||
|
||||
// Use normally
|
||||
const result = await generateText({
|
||||
model,
|
||||
messages: [{ role: "user", content: "Help me" }]
|
||||
})
|
||||
```
|
||||
</Tab>
|
||||
|
||||
<Tab title="Without AI SDK (Complex)">
|
||||
```typescript
|
||||
// Manual profile fetching
|
||||
const profileRes = await fetch('https://api.supermemory.ai/v4/profile', {
|
||||
method: 'POST',
|
||||
headers: { /* ... */ },
|
||||
body: JSON.stringify({ containerTag: "user-123" })
|
||||
})
|
||||
const profile = await profileRes.json()
|
||||
|
||||
// Manual prompt construction
|
||||
const systemPrompt = `User Profile:\n${profile.profile.static?.join('\n')}`
|
||||
|
||||
// Manual LLM call with profile
|
||||
const result = await generateText({
|
||||
model: openai("gpt-4"),
|
||||
messages: [
|
||||
{ role: "system", content: systemPrompt },
|
||||
{ role: "user", content: "Help me" }
|
||||
]
|
||||
})
|
||||
```
|
||||
</Tab>
|
||||
</Tabs>
|
||||
|
||||
## Limitations
|
||||
|
||||
- **Beta Feature**: The `withSupermemory` middleware is currently in beta
|
||||
- **Container Tag Required**: You must provide a valid container tag
|
||||
- **API Key Required**: Ensure `SUPERMEMORY_API_KEY` is set in your environment
|
||||
|
||||
## Next Steps
|
||||
|
||||
<CardGroup cols={2}>
|
||||
<Card title="User Profiles Concepts" icon="brain" href="/user-profiles">
|
||||
Understand how profiles work conceptually
|
||||
</Card>
|
||||
|
||||
<Card title="Memory Tools" icon="wrench" href="/integrations/ai-sdk">
|
||||
Add explicit memory operations to your agents
|
||||
</Card>
|
||||
|
||||
<Card title="API Reference" icon="code" href="https://api.supermemory.ai/v3/reference#tag/profile">
|
||||
Explore the underlying profile API
|
||||
</Card>
|
||||
|
||||
<Card title="NPM Package" icon="npm" href="https://www.npmjs.com/package/@supermemory/tools">
|
||||
View the package on NPM
|
||||
</Card>
|
||||
</CardGroup>
|
||||
|
||||
<Info>
|
||||
**Pro Tip**: Start with profile mode for general personalization, then experiment with query and full modes as you understand your use case better.
|
||||
</Info>
|
||||
|
|
@ -1,176 +0,0 @@
|
|||
---
|
||||
title: "Container Tags"
|
||||
sidebarTitle: "Container Tags"
|
||||
description: "The isolation boundary that groups and partitions memories by user, project, or any logical scope"
|
||||
icon: "folder"
|
||||
---
|
||||
|
||||
A **container tag** is the primary way you organize and isolate memories in Supermemory. It's a simple string identifier you attach to content when you add it — and that you pass back when you search, list, or update it.
|
||||
|
||||
Think of a container tag as a **namespace**: every memory tagged with `user_alex` lives in its own isolated space, completely separate from memories tagged `user_jordan`. This is what makes Supermemory safe to use in multi-tenant applications — one user can never see another user's memories unless you explicitly query across both tags.
|
||||
|
||||
<CardGroup cols={2}>
|
||||
<Card title="Group" icon="layers">
|
||||
Bucket memories by user, project, agent, workspace, or any boundary that makes sense for your app.
|
||||
</Card>
|
||||
<Card title="Isolate" icon="shield">
|
||||
Each container tag maps to its own vector namespace, so search and retrieval never leak across boundaries.
|
||||
</Card>
|
||||
</CardGroup>
|
||||
|
||||
---
|
||||
|
||||
## How it works
|
||||
|
||||
When you add a memory with a container tag, Supermemory automatically creates a **space** for that tag (scoped to your organization) if one doesn't already exist. You don't need to provision anything ahead of time — the first write with a new tag creates the container, and subsequent writes reuse it.
|
||||
|
||||
```typescript
|
||||
// First call auto-creates the "user_alex" container
|
||||
await client.add({
|
||||
content: "Alex prefers dark mode and concise answers",
|
||||
containerTag: "user_alex",
|
||||
});
|
||||
|
||||
// Later, retrieve only Alex's memories
|
||||
const results = await client.search.memories({
|
||||
q: "what are the user's UI preferences?",
|
||||
containerTag: "user_alex",
|
||||
});
|
||||
```
|
||||
|
||||
Under the hood, each container tag is hashed into a dedicated vector namespace. Embeddings, chunks, and memory entries for one tag are stored and searched independently of every other tag — there is no shared index to filter through, which is why isolation is strict rather than best-effort.
|
||||
|
||||
<Note>
|
||||
A container tag is an **opaque identifier you choose**. Supermemory does not parse meaning out of it — `user_123`, `project_mobile`, and `org:acme:team:growth` are all equally valid. Pick a convention that mirrors the access boundaries in your own application.
|
||||
</Note>
|
||||
|
||||
---
|
||||
|
||||
## Naming rules
|
||||
|
||||
Container tags are validated on every request. A tag must:
|
||||
|
||||
- Be **100 characters or less**
|
||||
- Contain only **alphanumeric characters, hyphens (`-`), underscores (`_`), and colons (`:`)**
|
||||
|
||||
Matching pattern: `^[a-zA-Z0-9_:-]+$`
|
||||
|
||||
```typescript
|
||||
// ✅ Valid
|
||||
"user_123"
|
||||
"project-mobile-app"
|
||||
"org:acme:user:john"
|
||||
"tenant_42_workspace_7"
|
||||
|
||||
// ❌ Invalid — spaces, slashes, and other symbols are rejected
|
||||
"user 123"
|
||||
"project/mobile"
|
||||
"team@acme"
|
||||
```
|
||||
|
||||
The colon is intentionally allowed so you can build **hierarchical** tags (for example `org:acme:user:john`) that encode several levels of structure in a single identifier.
|
||||
|
||||
---
|
||||
|
||||
## `containerTag` vs `containerTags`
|
||||
|
||||
Supermemory's current API uses a **single** `containerTag` string per request.
|
||||
|
||||
<Warning>
|
||||
The plural `containerTags` array field is **deprecated**. It still works for backward compatibility on older (`/v3`) endpoints, but new integrations should use the singular `containerTag` string. The `/v4` API only accepts `containerTag`.
|
||||
</Warning>
|
||||
|
||||
| API field | Type | Status |
|
||||
|-----------|------|--------|
|
||||
| `containerTag` | `string` | ✅ Current — use this |
|
||||
| `containerTags` | `string[]` | ⚠️ Deprecated |
|
||||
|
||||
---
|
||||
|
||||
## Where container tags are used
|
||||
|
||||
The same tag flows through the entire lifecycle of a memory. Pass it consistently and your data stays neatly partitioned.
|
||||
|
||||
| Operation | Behavior |
|
||||
|-----------|----------|
|
||||
| **Add** | Writes the memory into the tag's container (auto-creating the space). |
|
||||
| **Search** | Restricts retrieval to the given tag's namespace. |
|
||||
| **List** | Returns only memories belonging to the tag(s). |
|
||||
| **Update / Delete** | Targets the memory inside the specified tag's container. |
|
||||
|
||||
```typescript
|
||||
// Add
|
||||
await client.add({ content: "Q1 planning notes", containerTag: "project_q1" });
|
||||
|
||||
// Search within the same container
|
||||
await client.search.memories({ q: "planning", containerTag: "project_q1" });
|
||||
|
||||
// List everything in the container
|
||||
await client.documents.list({ containerTags: ["project_q1"] });
|
||||
```
|
||||
|
||||
---
|
||||
|
||||
## Access control
|
||||
|
||||
Container tags are also an **authorization boundary**, not just an organizational one. Two mechanisms can restrict which tags a given caller may touch:
|
||||
|
||||
- **API key scopes** — an API key can be limited to a specific set of container tags, with read or write permission per tag.
|
||||
- **Member restrictions** — an organization member can be granted access to only certain container tags.
|
||||
|
||||
When a request is restricted, Supermemory validates the requested tag against the caller's allowed set:
|
||||
|
||||
- Requesting a tag outside the allowed set returns `403 Forbidden`.
|
||||
- A write (add/update/delete) to a read-only tag returns `403 Forbidden`.
|
||||
- If no tag is supplied by a restricted caller, the request is automatically scoped to their allowed tag(s).
|
||||
|
||||
This means you can hand out an API key that is physically incapable of reading or writing another tenant's data, enforced at the data layer rather than in your application code.
|
||||
|
||||
---
|
||||
|
||||
## Per-container settings
|
||||
|
||||
Each container tag can carry its own configuration, independent of other tags in the same organization:
|
||||
|
||||
| Setting | Purpose |
|
||||
|---------|---------|
|
||||
| `name` | A human-friendly display name for the container. |
|
||||
| `entityContext` | A custom context prompt applied when processing documents in this container — useful for steering extraction and summarization per project or tenant. |
|
||||
|
||||
```typescript
|
||||
await client.containerTags.update("project_research", {
|
||||
entityContext: "This project contains research papers about machine learning.",
|
||||
});
|
||||
```
|
||||
|
||||
Container tags can also be **merged** when you need to consolidate two buckets of memories into one.
|
||||
|
||||
---
|
||||
|
||||
## Choosing a convention
|
||||
|
||||
Pick a tagging scheme that maps onto the isolation boundaries your application actually needs.
|
||||
|
||||
| Pattern | Example | Use case |
|
||||
|---------|---------|----------|
|
||||
| User isolation | `user_{userId}` | Per-user memory in a consumer app |
|
||||
| Project grouping | `project_{projectId}` | Project- or workspace-scoped content |
|
||||
| Agent scoping | `agent_{agentId}` | Separate long-term memory per AI agent |
|
||||
| Hierarchical | `org:{orgId}:user:{userId}` | Multi-level, multi-tenant SaaS |
|
||||
|
||||
<Tip>
|
||||
Keep tags **deterministic** — derive them directly from IDs you already have (a user ID, a tenant ID) so you can always reconstruct the right tag at query time without a lookup.
|
||||
</Tip>
|
||||
|
||||
---
|
||||
|
||||
## Next steps
|
||||
|
||||
<CardGroup cols={2}>
|
||||
<Card title="Organizing & Filtering" icon="filter" href="/concepts/filtering">
|
||||
Combine container tags with metadata filters for precise retrieval.
|
||||
</Card>
|
||||
<Card title="Adding Memories" icon="plus" href="/add-memories">
|
||||
See container tags in action across the add API.
|
||||
</Card>
|
||||
</CardGroup>
|
||||
|
|
@ -14,7 +14,7 @@ Raw text, conversations, notes, or any string content.
|
|||
```typescript
|
||||
await client.add({
|
||||
content: "User prefers dark mode and uses vim keybindings",
|
||||
containerTags: ["user_123"]
|
||||
containerTag: "user_123"
|
||||
});
|
||||
```
|
||||
|
||||
|
|
@ -29,7 +29,7 @@ Send a URL and Supermemory fetches, extracts, and indexes the content.
|
|||
```typescript
|
||||
await client.add({
|
||||
content: "https://docs.example.com/api-reference",
|
||||
containerTags: ["documentation"]
|
||||
containerTag: "documentation"
|
||||
});
|
||||
```
|
||||
|
||||
|
|
|
|||
|
|
@ -1,359 +0,0 @@
|
|||
---
|
||||
title: "Organizing & Filtering Memories"
|
||||
sidebarTitle: "Multi-Tenancy / Filtering"
|
||||
description: "Use container tags and metadata to organize and retrieve memories"
|
||||
icon: "users"
|
||||
---
|
||||
|
||||
Supermemory provides two ways to organize your memories:
|
||||
|
||||
<CardGroup cols={2}>
|
||||
<Card title="Container Tags" icon="folder">
|
||||
**Organize memories** into isolated spaces by user, project, or workspace
|
||||
</Card>
|
||||
<Card title="Metadata Filtering" icon="database">
|
||||
**Query memories** by custom properties like category, status, or date
|
||||
</Card>
|
||||
</CardGroup>
|
||||
|
||||
Both can be used independently or together for precise filtering.
|
||||
|
||||
---
|
||||
|
||||
## Container Tags
|
||||
|
||||
Container tags create isolated memory spaces. Use them to separate memories by user, project, or any logical boundary.
|
||||
|
||||
### Adding Memories with Tags
|
||||
|
||||
```typescript
|
||||
await client.add({
|
||||
content: "Meeting notes from Q1 planning",
|
||||
containerTags: ["user_123"]
|
||||
});
|
||||
```
|
||||
|
||||
### Searching with Tags
|
||||
|
||||
```typescript
|
||||
const results = await client.search.documents({
|
||||
q: "planning notes",
|
||||
containerTags: ["user_123"]
|
||||
});
|
||||
```
|
||||
|
||||
<Note>
|
||||
Container tags use **exact array matching**. A memory tagged `["user_123", "project_a"]` won't match a search for just `["user_123"]`.
|
||||
</Note>
|
||||
|
||||
### Recommended Patterns
|
||||
|
||||
| Pattern | Example | Use Case |
|
||||
|---------|---------|----------|
|
||||
| User isolation | `user_{userId}` | Per-user memories |
|
||||
| Project grouping | `project_{projectId}` | Project-specific content |
|
||||
| Hierarchical | `org_{orgId}_team_{teamId}` | Multi-level organization |
|
||||
|
||||
<AccordionGroup>
|
||||
<Accordion title="More Container Tag Examples">
|
||||
```typescript
|
||||
// Multi-tenant SaaS - isolate by organization and user
|
||||
await client.add({
|
||||
content: "Company policy document",
|
||||
containerTags: ["org_acme_user_john"]
|
||||
});
|
||||
|
||||
// Search only within that user's org context
|
||||
const results = await client.search.documents({
|
||||
q: "vacation policy",
|
||||
containerTags: ["org_acme_user_john"]
|
||||
});
|
||||
|
||||
// Project-based isolation
|
||||
await client.add({
|
||||
content: "Sprint 5 retrospective notes",
|
||||
containerTags: ["project_mobile_app"]
|
||||
});
|
||||
|
||||
// Time-based segmentation
|
||||
await client.add({
|
||||
content: "Q1 2024 financial report",
|
||||
containerTags: ["user_cfo_2024_q1"]
|
||||
});
|
||||
```
|
||||
|
||||
**API field differences:**
|
||||
| Endpoint | Field | Type |
|
||||
|----------|-------|------|
|
||||
| `/v3/search` | `containerTags` | Array |
|
||||
| `/v4/search` | `containerTag` | String |
|
||||
| `/v3/documents/list` | `containerTags` | Array |
|
||||
</Accordion>
|
||||
</AccordionGroup>
|
||||
|
||||
---
|
||||
|
||||
## Metadata
|
||||
|
||||
Metadata lets you attach custom properties to memories and filter by them later.
|
||||
|
||||
### Adding Memories with Metadata
|
||||
|
||||
```typescript
|
||||
await client.add({
|
||||
content: "Technical design document for auth system",
|
||||
containerTags: ["user_123"],
|
||||
metadata: {
|
||||
category: "engineering",
|
||||
priority: "high",
|
||||
year: 2024
|
||||
}
|
||||
});
|
||||
```
|
||||
|
||||
### Searching with Metadata Filters
|
||||
|
||||
Filters must be wrapped in `AND` or `OR` arrays:
|
||||
|
||||
```typescript
|
||||
const results = await client.search.documents({
|
||||
q: "design document",
|
||||
containerTags: ["user_123"],
|
||||
filters: {
|
||||
AND: [
|
||||
{ key: "category", value: "engineering" },
|
||||
{ key: "priority", value: "high" }
|
||||
]
|
||||
}
|
||||
});
|
||||
```
|
||||
|
||||
### Filter Types
|
||||
|
||||
| Type | Example | Description |
|
||||
|------|---------|-------------|
|
||||
| String equality | `{ key: "status", value: "published" }` | Exact match |
|
||||
| String contains | `{ filterType: "string_contains", key: "title", value: "react" }` | Substring match |
|
||||
| Numeric | `{ filterType: "numeric", key: "priority", value: "5", numericOperator: ">=" }` | Number comparison |
|
||||
| Array contains | `{ filterType: "array_contains", key: "tags", value: "important" }` | Check array membership |
|
||||
|
||||
### Combining Filters
|
||||
|
||||
Use `AND` and `OR` for complex queries:
|
||||
|
||||
```typescript
|
||||
const results = await client.search.documents({
|
||||
q: "meeting notes",
|
||||
filters: {
|
||||
AND: [
|
||||
{ key: "type", value: "meeting" },
|
||||
{
|
||||
OR: [
|
||||
{ key: "team", value: "engineering" },
|
||||
{ key: "team", value: "product" }
|
||||
]
|
||||
}
|
||||
]
|
||||
}
|
||||
});
|
||||
```
|
||||
|
||||
### Excluding Results
|
||||
|
||||
Use `negate: true` to exclude matches:
|
||||
|
||||
```typescript
|
||||
const results = await client.search.documents({
|
||||
q: "documentation",
|
||||
filters: {
|
||||
AND: [
|
||||
{ key: "status", value: "draft", negate: true }
|
||||
]
|
||||
}
|
||||
});
|
||||
```
|
||||
|
||||
<AccordionGroup>
|
||||
<Accordion title="More Metadata Filter Examples">
|
||||
**String contains (substring search):**
|
||||
```typescript
|
||||
// Find documents with "machine learning" in the description
|
||||
const results = await client.search.documents({
|
||||
q: "AI research",
|
||||
filters: {
|
||||
AND: [
|
||||
{
|
||||
filterType: "string_contains",
|
||||
key: "description",
|
||||
value: "machine learning",
|
||||
ignoreCase: true
|
||||
}
|
||||
]
|
||||
}
|
||||
});
|
||||
```
|
||||
|
||||
**Numeric comparisons:**
|
||||
```typescript
|
||||
// Find high-priority items created after a specific date
|
||||
const results = await client.search.documents({
|
||||
q: "tasks",
|
||||
filters: {
|
||||
AND: [
|
||||
{
|
||||
filterType: "numeric",
|
||||
key: "priority",
|
||||
value: "7",
|
||||
numericOperator: ">="
|
||||
},
|
||||
{
|
||||
filterType: "numeric",
|
||||
key: "created_timestamp",
|
||||
value: "1704067200", // Unix timestamp
|
||||
numericOperator: ">="
|
||||
}
|
||||
]
|
||||
}
|
||||
});
|
||||
```
|
||||
|
||||
**Array contains (check array membership):**
|
||||
```typescript
|
||||
// Find documents where a specific user is a participant
|
||||
const results = await client.search.documents({
|
||||
q: "meeting notes",
|
||||
filters: {
|
||||
AND: [
|
||||
{
|
||||
filterType: "array_contains",
|
||||
key: "participants",
|
||||
value: "alice@company.com"
|
||||
}
|
||||
]
|
||||
}
|
||||
});
|
||||
```
|
||||
|
||||
**Complex nested filters:**
|
||||
```typescript
|
||||
// (category = "tech" OR category = "science") AND status != "archived"
|
||||
const results = await client.search.documents({
|
||||
q: "research papers",
|
||||
filters: {
|
||||
AND: [
|
||||
{
|
||||
OR: [
|
||||
{ key: "category", value: "tech" },
|
||||
{ key: "category", value: "science" }
|
||||
]
|
||||
},
|
||||
{ key: "status", value: "archived", negate: true }
|
||||
]
|
||||
}
|
||||
});
|
||||
```
|
||||
|
||||
**Numeric operator negation mapping:**
|
||||
When using `negate: true`, operators flip:
|
||||
- `<` becomes `>=`
|
||||
- `<=` becomes `>`
|
||||
- `>` becomes `<=`
|
||||
- `>=` becomes `<`
|
||||
- `=` becomes `!=`
|
||||
</Accordion>
|
||||
|
||||
<Accordion title="Real-World Patterns">
|
||||
**User's work documents from 2024:**
|
||||
```typescript
|
||||
const results = await client.search.documents({
|
||||
q: "quarterly report",
|
||||
containerTags: ["user_123"],
|
||||
filters: {
|
||||
AND: [
|
||||
{ key: "category", value: "work" },
|
||||
{ key: "type", value: "report" },
|
||||
{ filterType: "numeric", key: "year", value: "2024", numericOperator: "=" }
|
||||
]
|
||||
}
|
||||
});
|
||||
```
|
||||
|
||||
**Team meeting notes with specific participants:**
|
||||
```typescript
|
||||
const results = await client.search.documents({
|
||||
q: "sprint planning",
|
||||
containerTags: ["project_alpha"],
|
||||
filters: {
|
||||
AND: [
|
||||
{ key: "type", value: "meeting" },
|
||||
{
|
||||
OR: [
|
||||
{ filterType: "array_contains", key: "participants", value: "alice" },
|
||||
{ filterType: "array_contains", key: "participants", value: "bob" }
|
||||
]
|
||||
}
|
||||
]
|
||||
}
|
||||
});
|
||||
```
|
||||
|
||||
**Exclude drafts and deprecated content:**
|
||||
```typescript
|
||||
const results = await client.search.documents({
|
||||
q: "documentation",
|
||||
filters: {
|
||||
AND: [
|
||||
{ key: "status", value: "draft", negate: true },
|
||||
{ filterType: "string_contains", key: "content", value: "deprecated", negate: true },
|
||||
{ filterType: "array_contains", key: "tags", value: "archived", negate: true }
|
||||
]
|
||||
}
|
||||
});
|
||||
```
|
||||
</Accordion>
|
||||
</AccordionGroup>
|
||||
|
||||
---
|
||||
|
||||
## Quick Reference
|
||||
|
||||
### When Adding Memories
|
||||
|
||||
```typescript
|
||||
await client.add({
|
||||
content: "Your content here",
|
||||
containerTags: ["user_123"], // Isolation
|
||||
metadata: { key: "value" } // Custom properties
|
||||
});
|
||||
```
|
||||
|
||||
### When Searching
|
||||
|
||||
```typescript
|
||||
const results = await client.search.documents({
|
||||
q: "search query",
|
||||
containerTags: ["user_123"], // Must match exactly
|
||||
filters: { // Optional metadata filters
|
||||
AND: [{ key: "status", value: "published" }]
|
||||
}
|
||||
});
|
||||
```
|
||||
|
||||
### Metadata Key Rules
|
||||
|
||||
- Allowed characters: `a-z`, `A-Z`, `0-9`, `_`, `-`, `.`
|
||||
- Max length: 64 characters
|
||||
- No spaces or special characters
|
||||
|
||||
---
|
||||
|
||||
## Next Steps
|
||||
|
||||
<CardGroup cols={2}>
|
||||
<Card title="Search" icon="search" href="/search">
|
||||
Apply filters in search queries
|
||||
</Card>
|
||||
<Card title="Add Memories" icon="plus" href="/add-memories">
|
||||
Add content with container tags and metadata
|
||||
</Card>
|
||||
</CardGroup>
|
||||
|
|
@ -205,7 +205,7 @@ client.add(
|
|||
# Add a user-specific memory
|
||||
client.add(
|
||||
content="User prefers Android over iOS",
|
||||
container_tags=["user_123"], # User-specific
|
||||
container_tag="user_123", # User-specific
|
||||
metadata={
|
||||
"type": "preference",
|
||||
"confidence": "high"
|
||||
|
|
@ -216,9 +216,9 @@ client.add(
|
|||
### 3. Hybrid Retrieval
|
||||
```python
|
||||
# Search combines both approaches
|
||||
results = client.documents.search(
|
||||
query="What phone should I recommend?",
|
||||
container_tags=["user_123"], # Gets user memories
|
||||
results = client.search.memories(
|
||||
q="What phone should I recommend?",
|
||||
container_tag="user_123", # Gets user memories
|
||||
# Also searches general knowledge
|
||||
)
|
||||
|
||||
|
|
|
|||
|
|
@ -95,13 +95,13 @@ Supermemory combines the best of both approaches in every search:
|
|||
</Card>
|
||||
</CardGroup>
|
||||
|
||||
With `searchMode: "hybrid"` (the default), you get both:
|
||||
Search memories and include the matching documents, and you get both:
|
||||
|
||||
```typescript
|
||||
const results = await client.search({
|
||||
const results = await client.search.memories({
|
||||
q: "how do I deploy the app?",
|
||||
containerTag: "user_123",
|
||||
searchMode: "hybrid"
|
||||
include: { documents: true }
|
||||
});
|
||||
|
||||
// Returns:
|
||||
|
|
@ -121,8 +121,9 @@ Two flags give you fine-grained control over result quality:
|
|||
Re-scores results using a cross-encoder model for better relevance:
|
||||
|
||||
```typescript
|
||||
const results = await client.search({
|
||||
const results = await client.search.memories({
|
||||
q: "complex technical question",
|
||||
containerTag: "user_123",
|
||||
rerank: true // +~100ms, significantly better ranking
|
||||
});
|
||||
```
|
||||
|
|
@ -134,8 +135,9 @@ const results = await client.search({
|
|||
Expands your query to capture more relevant results:
|
||||
|
||||
```typescript
|
||||
const results = await client.search({
|
||||
const results = await client.search.memories({
|
||||
q: "how to auth",
|
||||
containerTag: "user_123",
|
||||
rewriteQuery: true // Expands to "authentication login oauth jwt..."
|
||||
});
|
||||
```
|
||||
|
|
|
|||
|
|
@ -24,7 +24,7 @@ export async function POST(request: Request) {
|
|||
const { messages } = await request.json()
|
||||
|
||||
const result = await streamText({
|
||||
model: anthropic('claude-3-sonnet-20240229'),
|
||||
model: anthropic('claude-sonnet-4-5'),
|
||||
messages,
|
||||
tools: supermemoryTools(process.env.SUPERMEMORY_API_KEY!),
|
||||
system: `You are a helpful personal assistant. When users share information about themselves,
|
||||
|
|
@ -32,14 +32,14 @@ export async function POST(request: Request) {
|
|||
personalized responses. Always be proactive about remembering important details.`
|
||||
})
|
||||
|
||||
return result.toAIStreamResponse()
|
||||
return result.toUIMessageStreamResponse()
|
||||
}
|
||||
```
|
||||
|
||||
```typescript Client Component
|
||||
'use client'
|
||||
|
||||
import { useChat } from 'ai/react'
|
||||
import { useChat } from '@ai-sdk/react'
|
||||
|
||||
export default function PersonalAssistant() {
|
||||
const { messages, input, handleInputChange, handleSubmit } = useChat()
|
||||
|
|
@ -109,7 +109,7 @@ export async function POST(request: Request) {
|
|||
4. Always be empathetic and solution-focused`
|
||||
})
|
||||
|
||||
return result.toAIStreamResponse()
|
||||
return result.toUIMessageStreamResponse()
|
||||
}
|
||||
```
|
||||
|
||||
|
|
@ -130,7 +130,7 @@ export async function POST(request: Request) {
|
|||
const { messages, userId, courseId } = await request.json()
|
||||
|
||||
const result = await streamText({
|
||||
model: anthropic('claude-3-haiku-20240307'),
|
||||
model: anthropic('claude-haiku-4-5'),
|
||||
messages,
|
||||
tools: supermemoryTools(process.env.SUPERMEMORY_API_KEY!, {
|
||||
containerTags: [userId]
|
||||
|
|
@ -142,7 +142,7 @@ export async function POST(request: Request) {
|
|||
4. Tracking topics they've mastered vs topics they need more help with`
|
||||
})
|
||||
|
||||
return result.toAIStreamResponse()
|
||||
return result.toUIMessageStreamResponse()
|
||||
}
|
||||
```
|
||||
|
||||
|
|
@ -177,7 +177,7 @@ export async function POST(request: Request) {
|
|||
4. Track research progress and important discoveries`
|
||||
})
|
||||
|
||||
return result.toAIStreamResponse()
|
||||
return result.toUIMessageStreamResponse()
|
||||
}
|
||||
```
|
||||
|
||||
|
|
@ -230,7 +230,7 @@ export async function POST(request: Request) {
|
|||
const { messages, repositoryId } = await request.json()
|
||||
|
||||
const result = await streamText({
|
||||
model: anthropic('claude-3-sonnet-20240229'),
|
||||
model: anthropic('claude-sonnet-4-5'),
|
||||
messages,
|
||||
tools: {
|
||||
// Use individual tools for more control
|
||||
|
|
@ -262,7 +262,7 @@ export async function POST(request: Request) {
|
|||
4. Learn from debugging sessions and common issues`
|
||||
})
|
||||
|
||||
return result.toAIStreamResponse()
|
||||
return result.toUIMessageStreamResponse()
|
||||
}
|
||||
```
|
||||
|
||||
|
|
@ -313,7 +313,7 @@ export async function POST(request: Request) {
|
|||
3. Search for conflicts using searchMemories`
|
||||
})
|
||||
|
||||
return result.toAIStreamResponse()
|
||||
return result.toUIMessageStreamResponse()
|
||||
}
|
||||
```
|
||||
|
||||
|
|
|
|||
|
|
@ -480,12 +480,12 @@ If you cannot resolve the issue completely, prepare a clear summary for escalati
|
|||
}
|
||||
})
|
||||
|
||||
return result.toAIStreamResponse({
|
||||
data: {
|
||||
return result.toUIMessageStreamResponse({
|
||||
messageMetadata: () => ({
|
||||
needsEscalation,
|
||||
customerTier: customer.tier,
|
||||
contextCount: contextResults.length
|
||||
}
|
||||
})
|
||||
})
|
||||
|
||||
} catch (error) {
|
||||
|
|
@ -724,7 +724,7 @@ If you cannot resolve the issue completely, prepare a clear summary for escalati
|
|||
'use client'
|
||||
|
||||
import { useState, useEffect } from 'react'
|
||||
import { useChat } from 'ai/react'
|
||||
import { useChat } from '@ai-sdk/react'
|
||||
import { CustomerContextManager } from '@/lib/customer-context'
|
||||
|
||||
interface Customer {
|
||||
|
|
|
|||
|
|
@ -369,12 +369,12 @@ If the question cannot be answered from the provided documents, respond with: "I
|
|||
maxTokens: 1000
|
||||
})
|
||||
|
||||
return result.toAIStreamResponse({
|
||||
data: {
|
||||
return result.toUIMessageStreamResponse({
|
||||
messageMetadata: () => ({
|
||||
sources,
|
||||
searchResultsCount: searchResults.results.length,
|
||||
totalResults: searchResults.total
|
||||
}
|
||||
})
|
||||
})
|
||||
|
||||
} catch (error) {
|
||||
|
|
@ -525,7 +525,7 @@ If the question cannot be answered from the provided documents, respond with: "I
|
|||
'use client'
|
||||
|
||||
import { useState, useRef } from 'react'
|
||||
import { useChat } from 'ai/react'
|
||||
import { useChat } from '@ai-sdk/react'
|
||||
import { DocumentProcessor } from '@/lib/document-processor'
|
||||
|
||||
interface Document {
|
||||
|
|
|
|||
|
|
@ -610,10 +610,10 @@ Later:
|
|||
#### Return Streaming Response
|
||||
|
||||
```typescript
|
||||
return result.toAIStreamResponse()
|
||||
return result.toUIMessageStreamResponse()
|
||||
```
|
||||
|
||||
`toAIStreamResponse()` converts the streaming result into a format the frontend can consume. It:
|
||||
`toUIMessageStreamResponse()` converts the streaming result into a format the frontend can consume. It:
|
||||
- Sets appropriate headers for streaming
|
||||
- Formats data for the `useChat` hook
|
||||
- Handles errors gracefully
|
||||
|
|
@ -643,7 +643,7 @@ Catches any errors (API failures, tool errors, etc.) and returns a clean error r
|
|||
| **Memory Search** | Manual `search_user_memories()` call | AI SDK calls `searchMemories` tool automatically |
|
||||
| **Memory Add** | Manual `add_user_memory()` call | AI SDK calls `addMemory` tool automatically |
|
||||
| **Tool Decision** | You decide when to search/add | AI decides based on conversation context |
|
||||
| **Streaming** | Manual SSE formatting | `toAIStreamResponse()` handles it |
|
||||
| **Streaming** | Manual SSE formatting | `toUIMessageStreamResponse()` handles it |
|
||||
| **Error Handling** | Try/catch in each function | AI SDK handles tool errors |
|
||||
|
||||
**Python = Manual Control**
|
||||
|
|
@ -660,7 +660,7 @@ Replace `app/page.tsx`:
|
|||
|
||||
```typescript
|
||||
'use client'
|
||||
import { useChat } from 'ai/react'
|
||||
import { useChat } from '@ai-sdk/react'
|
||||
import { useState } from 'react'
|
||||
|
||||
export default function ChatPage() {
|
||||
|
|
@ -824,7 +824,7 @@ Create `scripts/check-memories.ts`:
|
|||
const userId = "your_user_id_here"
|
||||
const containerTag = `user_${userId}`
|
||||
|
||||
const response = await fetch('https://api.supermemory.ai/v3/memories', {
|
||||
const response = await fetch('https://api.supermemory.ai/v3/documents/list', {
|
||||
method: 'POST',
|
||||
headers: {
|
||||
'Authorization': `Bearer ${process.env.SUPERMEMORY_API_KEY}`,
|
||||
|
|
|
|||
|
|
@ -125,7 +125,7 @@ Get a specific document with its processing status.
|
|||
```typescript
|
||||
const doc = await client.documents.get("doc_abc123");
|
||||
|
||||
console.log(doc.status); // "queued" | "processing" | "done" | "failed"
|
||||
console.log(doc.status); // "queued" | "extracting" | "chunking" | "embedding" | "indexing" | "done" | "failed"
|
||||
console.log(doc.content);
|
||||
```
|
||||
</Tab>
|
||||
|
|
@ -153,6 +153,7 @@ Get a specific document with its processing status.
|
|||
| `extracting` | Extracting content (OCR, transcription) |
|
||||
| `chunking` | Breaking into searchable pieces |
|
||||
| `embedding` | Creating vector representations |
|
||||
| `indexing` | Indexing for retrieval |
|
||||
| `done` | Ready for search |
|
||||
| `failed` | Processing failed |
|
||||
|
||||
|
|
|
|||
|
|
@ -136,7 +136,6 @@ Look up past interactions:
|
|||
results = memory.search.memories(
|
||||
q="pasta recipes we discussed",
|
||||
container_tag="user_123",
|
||||
search_mode="hybrid",
|
||||
limit=5
|
||||
)
|
||||
|
||||
|
|
|
|||
|
|
@ -74,19 +74,19 @@ Both `containerTag` and `customId` are required.
|
|||
**Profile Mode (Default)** - Retrieves the user's complete profile:
|
||||
|
||||
```typescript
|
||||
const model = withSupermemory(openai("gpt-4"), { containerTag: "user-123", customId: "conv-1", mode: "profile" })
|
||||
const model = withSupermemory(openai("gpt-4o"), { containerTag: "user-123", customId: "conv-1", mode: "profile" })
|
||||
```
|
||||
|
||||
**Query Mode** - Searches memories based on the user's message:
|
||||
|
||||
```typescript
|
||||
const model = withSupermemory(openai("gpt-4"), { containerTag: "user-123", customId: "conv-1", mode: "query" })
|
||||
const model = withSupermemory(openai("gpt-4o"), { containerTag: "user-123", customId: "conv-1", mode: "query" })
|
||||
```
|
||||
|
||||
**Full Mode** - Combines profile AND query-based search:
|
||||
|
||||
```typescript
|
||||
const model = withSupermemory(openai("gpt-4"), { containerTag: "user-123", customId: "conv-1", mode: "full" })
|
||||
const model = withSupermemory(openai("gpt-4o"), { containerTag: "user-123", customId: "conv-1", mode: "full" })
|
||||
```
|
||||
|
||||
### Custom Prompt Templates
|
||||
|
|
@ -107,7 +107,7 @@ const claudePrompt = (data: MemoryPromptData) => `
|
|||
</context>
|
||||
`.trim()
|
||||
|
||||
const model = withSupermemory(anthropic("claude-3-sonnet"), {
|
||||
const model = withSupermemory(anthropic("claude-sonnet-4-5"), {
|
||||
containerTag: "user-123",
|
||||
customId: "conv-1",
|
||||
mode: "full",
|
||||
|
|
@ -118,7 +118,7 @@ const model = withSupermemory(anthropic("claude-3-sonnet"), {
|
|||
### Verbose Logging
|
||||
|
||||
```typescript
|
||||
const model = withSupermemory(openai("gpt-4"), {
|
||||
const model = withSupermemory(openai("gpt-4o"), {
|
||||
containerTag: "user-123",
|
||||
customId: "conv-1",
|
||||
verbose: true,
|
||||
|
|
@ -166,7 +166,7 @@ import { supermemoryTools } from "@supermemory/tools/ai-sdk"
|
|||
const anthropic = createAnthropic({ apiKey: "YOUR_ANTHROPIC_KEY" })
|
||||
|
||||
const result = await streamText({
|
||||
model: anthropic("claude-3-sonnet"),
|
||||
model: anthropic("claude-sonnet-4-5"),
|
||||
prompt: "Remember that my name is Alice",
|
||||
tools: supermemoryTools("YOUR_SUPERMEMORY_KEY")
|
||||
})
|
||||
|
|
@ -189,7 +189,7 @@ const result = await streamText({
|
|||
|
||||
```typescript
|
||||
const result = await streamText({
|
||||
model: anthropic("claude-3-sonnet"),
|
||||
model: anthropic("claude-sonnet-4-5"),
|
||||
prompt: "Remember that I'm allergic to peanuts",
|
||||
tools: supermemoryTools("API_KEY")
|
||||
})
|
||||
|
|
|
|||
|
|
@ -77,7 +77,6 @@ export const searchMemories = action({
|
|||
return await memory.search.memories({
|
||||
q: query,
|
||||
containerTag: userId,
|
||||
searchMode: "hybrid",
|
||||
limit: limit ?? 10,
|
||||
});
|
||||
},
|
||||
|
|
|
|||
|
|
@ -122,7 +122,6 @@ Pull up past interactions before running a crew:
|
|||
results = memory.search.memories(
|
||||
q="previous project recommendations",
|
||||
container_tag="user_abc",
|
||||
search_mode="hybrid",
|
||||
limit=10
|
||||
)
|
||||
|
||||
|
|
|
|||
|
|
@ -148,4 +148,4 @@ If you run your own supermemory API, set **`base_url`** (and any other host-spec
|
|||
</Card>
|
||||
</CardGroup>
|
||||
|
||||
Questions about the API or product? [Discord](https://supermemory.link/discord) · [support@supermemory.com](mailto:support@supermemory.com) · [Developer docs](/intro)
|
||||
Questions about the API or product? [Discord](https://supermemory.link/discord) · [support@supermemory.ai](mailto:support@supermemory.ai) · [Developer docs](/intro)
|
||||
|
|
|
|||
|
|
@ -137,7 +137,6 @@ Search returns both extracted memories and document chunks:
|
|||
results = memory.search.memories(
|
||||
q="async programming",
|
||||
container_tag="user_123",
|
||||
search_mode="hybrid", # Searches memories + document chunks
|
||||
limit=5
|
||||
)
|
||||
|
||||
|
|
|
|||
|
|
@ -154,7 +154,6 @@ Search returns both extracted memories and document chunks:
|
|||
results = memory.search.memories(
|
||||
q="graph algorithms",
|
||||
container_tag="user_123",
|
||||
search_mode="hybrid",
|
||||
limit=5
|
||||
)
|
||||
|
||||
|
|
|
|||
|
|
@ -289,7 +289,7 @@ interface DocumentWithMemories {
|
|||
url?: string | null;
|
||||
source?: string | null;
|
||||
type?: string | null;
|
||||
status: 'pending' | 'processing' | 'done' | 'failed';
|
||||
status: 'unknown' | 'queued' | 'extracting' | 'chunking' | 'embedding' | 'indexing' | 'done' | 'failed';
|
||||
metadata?: Record<string, string | number | boolean> | null;
|
||||
createdAt: string | Date;
|
||||
updatedAt: string | Date;
|
||||
|
|
|
|||
|
|
@ -135,7 +135,6 @@ Look up past interactions before running an agent:
|
|||
results = memory.search.memories(
|
||||
q="previous travel recommendations",
|
||||
container_tag="user_123",
|
||||
search_mode="hybrid",
|
||||
limit=5
|
||||
)
|
||||
|
||||
|
|
|
|||
|
|
@ -269,7 +269,7 @@ openclaw supermemory wipe # Delete all memories (requires confirma
|
|||
|
||||
Automatic per-channel separation is not supported yet. If you need this, let us know — with enough requests, we'll implement it right away.
|
||||
|
||||
<Card title="Request this feature" icon="mail" href="mailto:support@supermemory.com?subject=Feature%20Request%3A%20Per-Channel%20Container%20Tags&body=Hey%2C%0A%0AMy%20name%20is%20%5Byour%20name%5D.%20I%20just%20saw%20that%20you%20offer%20custom%20plugins.%0A%0AThis%20is%20my%20use%20case%3A%20%5Bdescribe%20your%20use%20case%5D%0A%0AI%20would%20love%20to%20have%20separate%20container%20tags%20for%20each%20channel%20so%20my%20session%20memories%20are%20automatically%20isolated.%0A%0AThanks!">
|
||||
<Card title="Request this feature" icon="mail" href="mailto:support@supermemory.ai?subject=Feature%20Request%3A%20Per-Channel%20Container%20Tags&body=Hey%2C%0A%0AMy%20name%20is%20%5Byour%20name%5D.%20I%20just%20saw%20that%20you%20offer%20custom%20plugins.%0A%0AThis%20is%20my%20use%20case%3A%20%5Bdescribe%20your%20use%20case%5D%0A%0AI%20would%20love%20to%20have%20separate%20container%20tags%20for%20each%20channel%20so%20my%20session%20memories%20are%20automatically%20isolated.%0A%0AThanks!">
|
||||
Email us with your use case.
|
||||
</Card>
|
||||
</Accordion>
|
||||
|
|
|
|||
|
|
@ -36,7 +36,7 @@ Both SDKs also work against [self-hosted Supermemory](/self-hosting/overview)
|
|||
});
|
||||
|
||||
// Add a memory
|
||||
await client.add({ content: "Meeting notes from Q1 planning", containerTags: ["user_123"] });
|
||||
await client.add({ content: "Meeting notes from Q1 planning", containerTag: "user_123" });
|
||||
|
||||
// Search memories
|
||||
const response = await client.search.documents({
|
||||
|
|
@ -57,7 +57,7 @@ Both SDKs also work against [self-hosted Supermemory](/self-hosting/overview)
|
|||
// Add with metadata
|
||||
await client.add({
|
||||
content: "Technical design doc",
|
||||
containerTags: ["user_123"],
|
||||
containerTag: "user_123",
|
||||
metadata: { category: "engineering", priority: "high" }
|
||||
});
|
||||
|
||||
|
|
@ -98,7 +98,7 @@ Both SDKs also work against [self-hosted Supermemory](/self-hosting/overview)
|
|||
)
|
||||
|
||||
# Add a memory
|
||||
client.add(content="Meeting notes from Q1 planning", container_tags=["user_123"])
|
||||
client.add(content="Meeting notes from Q1 planning", container_tag="user_123")
|
||||
|
||||
# Search memories
|
||||
response = client.search.documents(
|
||||
|
|
@ -119,7 +119,7 @@ Both SDKs also work against [self-hosted Supermemory](/self-hosting/overview)
|
|||
# Add with metadata
|
||||
client.add(
|
||||
content="Technical design doc",
|
||||
container_tags=["user_123"],
|
||||
container_tag="user_123",
|
||||
metadata={"category": "engineering", "priority": "high"}
|
||||
)
|
||||
|
||||
|
|
|
|||
|
|
@ -1,87 +0,0 @@
|
|||
---
|
||||
title: "Basic Listing"
|
||||
description: "Simple memory retrieval across languages"
|
||||
---
|
||||
|
||||
Simple memory retrieval examples for getting started with the list memories endpoint.
|
||||
|
||||
## Basic Usage
|
||||
|
||||
<Tabs>
|
||||
<Tab title="TypeScript">
|
||||
```typescript
|
||||
import Supermemory from 'supermemory';
|
||||
|
||||
const client = new Supermemory({
|
||||
apiKey: process.env.SUPERMEMORY_API_KEY!
|
||||
});
|
||||
|
||||
const response = await client.documents.list({ limit: 10 });
|
||||
console.log(response);
|
||||
```
|
||||
</Tab>
|
||||
<Tab title="Python">
|
||||
```python
|
||||
from supermemory import Supermemory
|
||||
import os
|
||||
|
||||
client = Supermemory(api_key=os.environ.get("SUPERMEMORY_API_KEY"))
|
||||
response = client.documents.list(limit=10)
|
||||
print(response)
|
||||
```
|
||||
</Tab>
|
||||
<Tab title="cURL">
|
||||
```bash
|
||||
curl -X POST "https://api.supermemory.ai/v3/documents/list" \
|
||||
-H "Authorization: Bearer $SUPERMEMORY_API_KEY" \
|
||||
-H "Content-Type: application/json" \
|
||||
-d '{"limit": 10}'
|
||||
```
|
||||
</Tab>
|
||||
</Tabs>
|
||||
|
||||
## With Custom Parameters
|
||||
|
||||
<Tabs>
|
||||
<Tab title="TypeScript">
|
||||
```typescript
|
||||
const response = await client.documents.list({
|
||||
containerTags: ["user_123"],
|
||||
limit: 20,
|
||||
sort: "updatedAt",
|
||||
order: "desc"
|
||||
});
|
||||
|
||||
console.log(`Found ${response.memories.length} memories`);
|
||||
```
|
||||
</Tab>
|
||||
<Tab title="Python">
|
||||
```python
|
||||
response = client.documents.list(
|
||||
container_tags=["user_123"],
|
||||
limit=20,
|
||||
sort="updatedAt",
|
||||
order="desc"
|
||||
)
|
||||
|
||||
print(f"Found {len(response.memories)} memories")
|
||||
```
|
||||
</Tab>
|
||||
<Tab title="cURL">
|
||||
```bash
|
||||
curl -X POST "https://api.supermemory.ai/v3/documents/list" \
|
||||
-H "Authorization: Bearer $SUPERMEMORY_API_KEY" \
|
||||
-H "Content-Type: application/json" \
|
||||
-d '{
|
||||
"containerTags": ["user_123"],
|
||||
"limit": 20,
|
||||
"sort": "updatedAt",
|
||||
"order": "desc"
|
||||
}'
|
||||
```
|
||||
</Tab>
|
||||
</Tabs>
|
||||
|
||||
<Info>
|
||||
Start with small `limit` values (10-20) when testing to avoid overwhelming responses.
|
||||
</Info>
|
||||
|
|
@ -1,506 +0,0 @@
|
|||
---
|
||||
title: "Filtering Memories"
|
||||
description: "Filter memories by container tags and metadata using SQL-based filtering"
|
||||
---
|
||||
|
||||
Filter memories using container tags and metadata. The filtering system uses SQL query construction, so you need to structure your filters like database queries.
|
||||
|
||||
## Filter by Container Tags
|
||||
|
||||
Container tags use exact array matching - memories must have the exact same tags in the same order.
|
||||
|
||||
<Tabs>
|
||||
<Tab title="TypeScript">
|
||||
```typescript
|
||||
// Single tag - matches memories with exactly ["user_123"]
|
||||
const userMemories = await client.documents.list({
|
||||
containerTags: ["user_123"]
|
||||
});
|
||||
|
||||
// Multiple tags - matches memories with exactly ["user_123", "project_ai"]
|
||||
const projectMemories = await client.documents.list({
|
||||
containerTags: ["user_123", "project_ai"]
|
||||
});
|
||||
```
|
||||
</Tab>
|
||||
<Tab title="Python">
|
||||
```python
|
||||
# Single tag
|
||||
user_memories = client.documents.list(container_tags=["user_123"])
|
||||
|
||||
# Multiple tags (exact match)
|
||||
project_memories = client.documents.list(
|
||||
container_tags=["user_123", "project_ai"]
|
||||
)
|
||||
```
|
||||
</Tab>
|
||||
<Tab title="cURL">
|
||||
```bash
|
||||
# Single tag
|
||||
curl -X POST "https://api.supermemory.ai/v3/documents/list" \
|
||||
-H "Authorization: Bearer $SUPERMEMORY_API_KEY" \
|
||||
-H "Content-Type: application/json" \
|
||||
-d '{"containerTags": ["user_123"]}'
|
||||
|
||||
# Multiple tags
|
||||
curl -X POST "https://api.supermemory.ai/v3/documents/list" \
|
||||
-H "Authorization: Bearer $SUPERMEMORY_API_KEY" \
|
||||
-H "Content-Type: application/json" \
|
||||
-d '{"containerTags": ["user_123", "project_ai"]}'
|
||||
```
|
||||
</Tab>
|
||||
</Tabs>
|
||||
|
||||
## Metadata Filtering with SQL Logic
|
||||
|
||||
The `filters` parameter allows filtering by metadata fields using SQL-like query structures. Since we use SQL query construction in the backend, you need to structure your filters like database queries with explicit AND/OR logic.
|
||||
|
||||
### Why This Structure?
|
||||
|
||||
In SQL databases, `AND` has higher precedence than `OR`. Without explicit grouping, a query like:
|
||||
```
|
||||
category = 'programming' OR framework = 'react' AND difficulty = 'advanced'
|
||||
```
|
||||
|
||||
Is interpreted as:
|
||||
```
|
||||
category = 'programming' OR (framework = 'react' AND difficulty = 'advanced')
|
||||
```
|
||||
|
||||
The JSON structure forces explicit grouping to prevent unexpected results.
|
||||
|
||||
<Info>
|
||||
**Filter Structure Rules:**
|
||||
- Always wrap conditions in `AND` or `OR` arrays (even single conditions)
|
||||
- Pass the filter as an object (TypeScript/Python) or JSON string (cURL)
|
||||
- Each condition needs `key`, `value`, and `negate` properties
|
||||
- `negate: false` for normal matching, `negate: true` for exclusion
|
||||
</Info>
|
||||
|
||||
### Simple Metadata Filter
|
||||
|
||||
<Tabs>
|
||||
<Tab title="TypeScript">
|
||||
```typescript
|
||||
// Filter by single metadata field
|
||||
const programmingMemories = await client.documents.list({
|
||||
filters: {
|
||||
AND: [
|
||||
{ key: "category", value: "programming", negate: false }
|
||||
]
|
||||
}
|
||||
});
|
||||
```
|
||||
</Tab>
|
||||
<Tab title="Python">
|
||||
```python
|
||||
# Filter by single metadata field
|
||||
programming_memories = client.documents.list(
|
||||
filters={
|
||||
"AND": [
|
||||
{"key": "category", "value": "programming", "negate": False}
|
||||
]
|
||||
}
|
||||
)
|
||||
```
|
||||
</Tab>
|
||||
<Tab title="cURL">
|
||||
```bash
|
||||
curl -X POST "https://api.supermemory.ai/v3/documents/list" \
|
||||
-H "Authorization: Bearer $SUPERMEMORY_API_KEY" \
|
||||
-H "Content-Type: application/json" \
|
||||
-d '{
|
||||
"filters": "{\"AND\":[{\"key\":\"category\",\"value\":\"programming\",\"negate\":false}]}"
|
||||
}'
|
||||
```
|
||||
</Tab>
|
||||
</Tabs>
|
||||
|
||||
### Multiple Conditions (AND Logic)
|
||||
|
||||
<Tabs>
|
||||
<Tab title="TypeScript">
|
||||
```typescript
|
||||
// All conditions must match
|
||||
const reactTutorials = await client.documents.list({
|
||||
filters: {
|
||||
AND: [
|
||||
{ key: "category", value: "tutorial", negate: false },
|
||||
{ key: "framework", value: "react", negate: false },
|
||||
{ key: "difficulty", value: "beginner", negate: false }
|
||||
]
|
||||
}
|
||||
});
|
||||
```
|
||||
</Tab>
|
||||
<Tab title="Python">
|
||||
```python
|
||||
# All conditions must match
|
||||
react_tutorials = client.documents.list(
|
||||
filters={
|
||||
"AND": [
|
||||
{"key": "category", "value": "tutorial", "negate": False},
|
||||
{"key": "framework", "value": "react", "negate": False},
|
||||
{"key": "difficulty", "value": "beginner", "negate": False}
|
||||
]
|
||||
}
|
||||
)
|
||||
```
|
||||
</Tab>
|
||||
<Tab title="cURL">
|
||||
```bash
|
||||
curl -X POST "https://api.supermemory.ai/v3/documents/list" \
|
||||
-H "Authorization: Bearer $SUPERMEMORY_API_KEY" \
|
||||
-H "Content-Type: application/json" \
|
||||
-d '{
|
||||
"filters": "{\"AND\":[{\"key\":\"category\",\"value\":\"tutorial\",\"negate\":false},{\"key\":\"framework\",\"value\":\"react\",\"negate\":false}]}"
|
||||
}'
|
||||
```
|
||||
</Tab>
|
||||
</Tabs>
|
||||
|
||||
### Alternative Conditions (OR Logic)
|
||||
|
||||
<Tabs>
|
||||
<Tab title="TypeScript">
|
||||
```typescript
|
||||
// Any condition can match
|
||||
const frontendMemories = await client.documents.list({
|
||||
filters: {
|
||||
OR: [
|
||||
{ key: "framework", value: "react", negate: false },
|
||||
{ key: "framework", value: "vue", negate: false },
|
||||
{ key: "framework", value: "angular", negate: false }
|
||||
]
|
||||
}
|
||||
});
|
||||
```
|
||||
</Tab>
|
||||
<Tab title="Python">
|
||||
```python
|
||||
# Any condition can match
|
||||
frontend_memories = client.documents.list(
|
||||
filters={
|
||||
"OR": [
|
||||
{"key": "framework", "value": "react", "negate": False},
|
||||
{"key": "framework", "value": "vue", "negate": False},
|
||||
{"key": "framework", "value": "angular", "negate": False}
|
||||
]
|
||||
}
|
||||
)
|
||||
```
|
||||
</Tab>
|
||||
<Tab title="cURL">
|
||||
```bash
|
||||
curl -X POST "https://api.supermemory.ai/v3/documents/list" \
|
||||
-H "Authorization: Bearer $SUPERMEMORY_API_KEY" \
|
||||
-H "Content-Type: application/json" \
|
||||
-d '{
|
||||
"filters": "{\"OR\":[{\"key\":\"framework\",\"value\":\"react\",\"negate\":false},{\"key\":\"framework\",\"value\":\"vue\",\"negate\":false}]}"
|
||||
}'
|
||||
```
|
||||
</Tab>
|
||||
</Tabs>
|
||||
|
||||
### Complex Nested Logic
|
||||
|
||||
<Tabs>
|
||||
<Tab title="TypeScript">
|
||||
```typescript
|
||||
// Complex logic: programming AND (react OR advanced difficulty)
|
||||
const advancedContent = await client.documents.list({
|
||||
filters: {
|
||||
AND: [
|
||||
{ key: "category", value: "programming", negate: false },
|
||||
{
|
||||
OR: [
|
||||
{ key: "framework", value: "react", negate: false },
|
||||
{ key: "difficulty", value: "advanced", negate: false }
|
||||
]
|
||||
}
|
||||
]
|
||||
}
|
||||
});
|
||||
```
|
||||
</Tab>
|
||||
<Tab title="Python">
|
||||
```python
|
||||
# Complex logic: programming AND (react OR advanced difficulty)
|
||||
advanced_content = client.documents.list(
|
||||
filters={
|
||||
"AND": [
|
||||
{"key": "category", "value": "programming", "negate": False},
|
||||
{
|
||||
"OR": [
|
||||
{"key": "framework", "value": "react", "negate": False},
|
||||
{"key": "difficulty", "value": "advanced", "negate": False}
|
||||
]
|
||||
}
|
||||
]
|
||||
}
|
||||
)
|
||||
```
|
||||
</Tab>
|
||||
<Tab title="cURL">
|
||||
```bash
|
||||
curl -X POST "https://api.supermemory.ai/v3/documents/list" \
|
||||
-H "Authorization: Bearer $SUPERMEMORY_API_KEY" \
|
||||
-H "Content-Type: application/json" \
|
||||
-d '{
|
||||
"filters": "{\"AND\":[{\"key\":\"category\",\"value\":\"programming\",\"negate\":false},{\"OR\":[{\"key\":\"framework\",\"value\":\"react\",\"negate\":false},{\"key\":\"difficulty\",\"value\":\"advanced\",\"negate\":false}]}]}"
|
||||
}'
|
||||
```
|
||||
</Tab>
|
||||
</Tabs>
|
||||
|
||||
## Array Contains Filtering
|
||||
|
||||
Filter memories that contain specific values in array fields like participants, tags, or team members.
|
||||
|
||||
### Basic Array Contains
|
||||
|
||||
<Tabs>
|
||||
<Tab title="TypeScript">
|
||||
```typescript
|
||||
// Find memories where john.doe participated
|
||||
const meetingMemories = await client.documents.list({
|
||||
filters: {
|
||||
AND: [
|
||||
{
|
||||
key: "participants",
|
||||
value: "john.doe",
|
||||
filterType: "array_contains",
|
||||
negate: false
|
||||
}
|
||||
]
|
||||
}
|
||||
});
|
||||
```
|
||||
</Tab>
|
||||
<Tab title="Python">
|
||||
```python
|
||||
# Find memories where john.doe participated
|
||||
meeting_memories = client.documents.list(
|
||||
filters={
|
||||
"AND": [
|
||||
{
|
||||
"key": "participants",
|
||||
"value": "john.doe",
|
||||
"filterType": "array_contains",
|
||||
"negate": False
|
||||
}
|
||||
]
|
||||
}
|
||||
)
|
||||
```
|
||||
</Tab>
|
||||
<Tab title="cURL">
|
||||
```bash
|
||||
curl -X POST "https://api.supermemory.ai/v3/documents/list" \
|
||||
-H "Authorization: Bearer $SUPERMEMORY_API_KEY" \
|
||||
-H "Content-Type: application/json" \
|
||||
-d '{
|
||||
"filters": "{\"AND\":[{\"key\":\"participants\",\"value\":\"john.doe\",\"filterType\":\"array_contains\",\"negate\":false}]}"
|
||||
}'
|
||||
```
|
||||
</Tab>
|
||||
</Tabs>
|
||||
|
||||
### Array Contains with Exclusion
|
||||
|
||||
<Tabs>
|
||||
<Tab title="TypeScript">
|
||||
```typescript
|
||||
// Find memories that don't include a specific team member
|
||||
const filteredMemories = await client.documents.list({
|
||||
filters: {
|
||||
AND: [
|
||||
{
|
||||
key: "reviewers",
|
||||
value: "external.consultant",
|
||||
filterType: "array_contains",
|
||||
negate: true // Exclude memories with external consultants
|
||||
},
|
||||
{
|
||||
key: "project_tags",
|
||||
value: "internal-only",
|
||||
filterType: "array_contains",
|
||||
negate: false
|
||||
}
|
||||
]
|
||||
}
|
||||
});
|
||||
```
|
||||
</Tab>
|
||||
<Tab title="Python">
|
||||
```python
|
||||
# Find memories that don't include a specific team member
|
||||
filtered_memories = client.documents.list(
|
||||
filters={
|
||||
"AND": [
|
||||
{
|
||||
"key": "reviewers",
|
||||
"value": "external.consultant",
|
||||
"filterType": "array_contains",
|
||||
"negate": True # Exclude memories with external consultants
|
||||
},
|
||||
{
|
||||
"key": "project_tags",
|
||||
"value": "internal-only",
|
||||
"filterType": "array_contains",
|
||||
"negate": False
|
||||
}
|
||||
]
|
||||
}
|
||||
)
|
||||
```
|
||||
</Tab>
|
||||
<Tab title="cURL">
|
||||
```bash
|
||||
curl -X POST "https://api.supermemory.ai/v3/documents/list" \
|
||||
-H "Authorization: Bearer $SUPERMEMORY_API_KEY" \
|
||||
-H "Content-Type: application/json" \
|
||||
-d '{
|
||||
"filters": "{\"AND\":[{\"key\":\"reviewers\",\"value\":\"external.consultant\",\"filterType\":\"array_contains\",\"negate\":true},{\"key\":\"project_tags\",\"value\":\"internal-only\",\"filterType\":\"array_contains\",\"negate\":false}]}"
|
||||
}'
|
||||
```
|
||||
</Tab>
|
||||
</Tabs>
|
||||
|
||||
### Multiple Array Contains (OR Logic)
|
||||
|
||||
<Tabs>
|
||||
<Tab title="TypeScript">
|
||||
```typescript
|
||||
// Find memories involving any of several team leads
|
||||
const leadershipMemories = await client.documents.list({
|
||||
filters: {
|
||||
OR: [
|
||||
{
|
||||
key: "attendees",
|
||||
value: "engineering.lead",
|
||||
filterType: "array_contains"
|
||||
},
|
||||
{
|
||||
key: "attendees",
|
||||
value: "product.lead",
|
||||
filterType: "array_contains"
|
||||
},
|
||||
{
|
||||
key: "attendees",
|
||||
value: "design.lead",
|
||||
filterType: "array_contains"
|
||||
}
|
||||
]
|
||||
},
|
||||
sort: "updatedAt",
|
||||
order: "desc"
|
||||
});
|
||||
```
|
||||
</Tab>
|
||||
<Tab title="Python">
|
||||
```python
|
||||
# Find memories involving any of several team leads
|
||||
leadership_memories = client.documents.list(
|
||||
filters={
|
||||
"OR": [
|
||||
{
|
||||
"key": "attendees",
|
||||
"value": "engineering.lead",
|
||||
"filterType": "array_contains"
|
||||
},
|
||||
{
|
||||
"key": "attendees",
|
||||
"value": "product.lead",
|
||||
"filterType": "array_contains"
|
||||
},
|
||||
{
|
||||
"key": "attendees",
|
||||
"value": "design.lead",
|
||||
"filterType": "array_contains"
|
||||
}
|
||||
]
|
||||
},
|
||||
sort="updatedAt",
|
||||
order="desc"
|
||||
)
|
||||
```
|
||||
</Tab>
|
||||
<Tab title="cURL">
|
||||
```bash
|
||||
curl -X POST "https://api.supermemory.ai/v3/documents/list" \
|
||||
-H "Authorization: Bearer $SUPERMEMORY_API_KEY" \
|
||||
-H "Content-Type: application/json" \
|
||||
-d '{
|
||||
"filters": "{\"OR\":[{\"key\":\"attendees\",\"value\":\"engineering.lead\",\"filterType\":\"array_contains\"},{\"key\":\"attendees\",\"value\":\"product.lead\",\"filterType\":\"array_contains\"},{\"key\":\"attendees\",\"value\":\"design.lead\",\"filterType\":\"array_contains\"}]}",
|
||||
"sort": "updatedAt",
|
||||
"order": "desc"
|
||||
}'
|
||||
```
|
||||
</Tab>
|
||||
</Tabs>
|
||||
|
||||
## Combined Container Tags + Metadata Filtering
|
||||
|
||||
<Tabs>
|
||||
<Tab title="TypeScript">
|
||||
```typescript
|
||||
const filteredMemories = await client.documents.list({
|
||||
containerTags: ["user_123"],
|
||||
filters: {
|
||||
AND: [
|
||||
{ key: "category", value: "tutorial", negate: false },
|
||||
{ key: "framework", value: "react", negate: false }
|
||||
]
|
||||
},
|
||||
sort: "updatedAt",
|
||||
order: "desc",
|
||||
limit: 50
|
||||
});
|
||||
```
|
||||
</Tab>
|
||||
<Tab title="Python">
|
||||
```python
|
||||
filtered_memories = client.documents.list(
|
||||
container_tags=["user_123"],
|
||||
filters={
|
||||
"AND": [
|
||||
{"key": "category", "value": "tutorial", "negate": False},
|
||||
{"key": "framework", "value": "react", "negate": False}
|
||||
]
|
||||
},
|
||||
sort="updatedAt",
|
||||
order="desc",
|
||||
limit=50
|
||||
)
|
||||
```
|
||||
</Tab>
|
||||
<Tab title="cURL">
|
||||
```bash
|
||||
curl -X POST "https://api.supermemory.ai/v3/documents/list" \
|
||||
-H "Authorization: Bearer $SUPERMEMORY_API_KEY" \
|
||||
-H "Content-Type: application/json" \
|
||||
-d '{
|
||||
"containerTags": ["user_123"],
|
||||
"filters": "{\"AND\":[{\"key\":\"category\",\"value\":\"tutorial\",\"negate\":false},{\"key\":\"framework\",\"value\":\"react\",\"negate\":false}]}",
|
||||
"sort": "updatedAt",
|
||||
"order": "desc",
|
||||
"limit": 50
|
||||
}'
|
||||
```
|
||||
</Tab>
|
||||
</Tabs>
|
||||
|
||||
<Warning>
|
||||
**Common Mistakes:**
|
||||
- Using bare condition objects: `{"key": "category", "value": "programming"}` without wrapping in `AND` or `OR`
|
||||
- Missing negate property: always include `"negate": false` or `"negate": true`
|
||||
- For cURL requests: forgetting to properly escape the JSON string
|
||||
</Warning>
|
||||
|
||||
<Note>
|
||||
**Container Tags vs Metadata Filtering:**
|
||||
- Container tags: Exact array matching for organizational grouping
|
||||
- Metadata filters: SQL-like queries on custom metadata fields with complex logic
|
||||
- Both can be combined for powerful filtering capabilities
|
||||
</Note>
|
||||
|
|
@ -1,119 +0,0 @@
|
|||
---
|
||||
title: "Status Monitoring"
|
||||
description: "Monitor memory processing status and completion rates"
|
||||
---
|
||||
|
||||
Monitor memory processing status and track completion rates using the list endpoint.
|
||||
|
||||
## Status Overview
|
||||
|
||||
<Tabs>
|
||||
<Tab title="TypeScript">
|
||||
```typescript
|
||||
const response = await client.documents.list({ limit: 100 });
|
||||
|
||||
const statusCounts = response.memories.reduce((acc: any, memory) => {
|
||||
acc[memory.status] = (acc[memory.status] || 0) + 1;
|
||||
return acc;
|
||||
}, {});
|
||||
|
||||
console.log('Status breakdown:', statusCounts);
|
||||
```
|
||||
</Tab>
|
||||
<Tab title="Python">
|
||||
```python
|
||||
response = client.documents.list(limit=100)
|
||||
|
||||
status_counts = {}
|
||||
for memory in response.memories:
|
||||
status = memory.status
|
||||
status_counts[status] = status_counts.get(status, 0) + 1
|
||||
|
||||
print("Status breakdown:", status_counts)
|
||||
```
|
||||
</Tab>
|
||||
<Tab title="cURL">
|
||||
```bash
|
||||
curl -X POST "https://api.supermemory.ai/v3/documents/list" \
|
||||
-H "Authorization: Bearer $SUPERMEMORY_API_KEY" \
|
||||
-H "Content-Type: application/json" \
|
||||
-d '{"limit": 100}' | \
|
||||
jq '.memories | group_by(.status) | map({status: .[0].status, count: length})'
|
||||
```
|
||||
</Tab>
|
||||
</Tabs>
|
||||
|
||||
## Filter Processing Memories
|
||||
|
||||
<Tabs>
|
||||
<Tab title="TypeScript">
|
||||
```typescript
|
||||
const response = await client.documents.list({ limit: 100 });
|
||||
|
||||
const processing = response.memories.filter(m =>
|
||||
['queued', 'extracting', 'chunking', 'embedding', 'indexing'].includes(m.status)
|
||||
);
|
||||
|
||||
console.log(`${processing.length} memories currently processing`);
|
||||
```
|
||||
</Tab>
|
||||
<Tab title="Python">
|
||||
```python
|
||||
response = client.documents.list(limit=100)
|
||||
|
||||
processing_statuses = ['queued', 'extracting', 'chunking', 'embedding', 'indexing']
|
||||
processing = [m for m in response.memories if m.status in processing_statuses]
|
||||
|
||||
print(f"{len(processing)} memories currently processing")
|
||||
```
|
||||
</Tab>
|
||||
<Tab title="cURL">
|
||||
```bash
|
||||
curl -X POST "https://api.supermemory.ai/v3/documents/list" \
|
||||
-H "Authorization: Bearer $SUPERMEMORY_API_KEY" \
|
||||
-H "Content-Type: application/json" \
|
||||
-d '{"limit": 100}' | \
|
||||
jq '.memories[] | select(.status | IN("queued", "extracting", "chunking", "embedding", "indexing"))'
|
||||
```
|
||||
</Tab>
|
||||
</Tabs>
|
||||
|
||||
## Failed Memories
|
||||
|
||||
<Tabs>
|
||||
<Tab title="TypeScript">
|
||||
```typescript
|
||||
const response = await client.documents.list({ limit: 100 });
|
||||
|
||||
const failedMemories = response.memories.filter(m => m.status === 'failed');
|
||||
|
||||
failedMemories.forEach(memory => {
|
||||
console.log(`Failed: ${memory.id} - ${memory.title || 'Untitled'}`);
|
||||
});
|
||||
```
|
||||
</Tab>
|
||||
<Tab title="Python">
|
||||
```python
|
||||
response = client.documents.list(limit=100)
|
||||
|
||||
failed_memories = [m for m in response.memories if m.status == 'failed']
|
||||
|
||||
for memory in failed_memories:
|
||||
title = memory.title or 'Untitled'
|
||||
print(f"Failed: {memory.id} - {title}")
|
||||
```
|
||||
</Tab>
|
||||
<Tab title="cURL">
|
||||
```bash
|
||||
curl -X POST "https://api.supermemory.ai/v3/documents/list" \
|
||||
-H "Authorization: Bearer $SUPERMEMORY_API_KEY" \
|
||||
-H "Content-Type: application/json" \
|
||||
-d '{"limit": 100}' | \
|
||||
jq '.memories[] | select(.status == "failed") | {id, title, status}'
|
||||
```
|
||||
</Tab>
|
||||
</Tabs>
|
||||
|
||||
<Note>
|
||||
For real-time monitoring of individual memories, use the [Track Processing Status](/memory-api/track-progress) guide.
|
||||
</Note>
|
||||
|
|
@ -1,110 +0,0 @@
|
|||
---
|
||||
title: "Pagination"
|
||||
description: "Handle large memory collections with pagination"
|
||||
---
|
||||
|
||||
Handle large memory collections efficiently using pagination to process data in manageable chunks.
|
||||
|
||||
## Basic Pagination
|
||||
|
||||
<Tabs>
|
||||
<Tab title="TypeScript">
|
||||
```typescript
|
||||
// Get first page
|
||||
const page1 = await client.documents.list({
|
||||
limit: 20,
|
||||
page: 1
|
||||
});
|
||||
|
||||
// Get next page
|
||||
const page2 = await client.documents.list({
|
||||
limit: 20,
|
||||
page: 2
|
||||
});
|
||||
|
||||
console.log(`Page 1: ${page1.memories.length} memories`);
|
||||
console.log(`Page 2: ${page2.memories.length} memories`);
|
||||
```
|
||||
</Tab>
|
||||
<Tab title="Python">
|
||||
```python
|
||||
# Get first page
|
||||
page1 = client.documents.list(limit=20, page=1)
|
||||
|
||||
# Get next page
|
||||
page2 = client.documents.list(limit=20, page=2)
|
||||
|
||||
print(f"Page 1: {len(page1.memories)} memories")
|
||||
print(f"Page 2: {len(page2.memories)} memories")
|
||||
```
|
||||
</Tab>
|
||||
<Tab title="cURL">
|
||||
```bash
|
||||
# Get first page
|
||||
curl -X POST "https://api.supermemory.ai/v3/documents/list" \
|
||||
-H "Authorization: Bearer $SUPERMEMORY_API_KEY" \
|
||||
-H "Content-Type: application/json" \
|
||||
-d '{"limit": 20, "page": 1}'
|
||||
|
||||
# Get next page
|
||||
curl -X POST "https://api.supermemory.ai/v3/documents/list" \
|
||||
-H "Authorization: Bearer $SUPERMEMORY_API_KEY" \
|
||||
-H "Content-Type: application/json" \
|
||||
-d '{"limit": 20, "page": 2}'
|
||||
```
|
||||
</Tab>
|
||||
</Tabs>
|
||||
|
||||
## Loop Through Pages
|
||||
|
||||
<Tabs>
|
||||
<Tab title="TypeScript">
|
||||
```typescript
|
||||
let currentPage = 1;
|
||||
let hasMore = true;
|
||||
|
||||
while (hasMore) {
|
||||
const response = await client.documents.list({
|
||||
page: currentPage,
|
||||
limit: 50
|
||||
});
|
||||
|
||||
console.log(`Page ${currentPage}: ${response.memories.length} memories`);
|
||||
|
||||
hasMore = currentPage < response.pagination.totalPages;
|
||||
currentPage++;
|
||||
}
|
||||
```
|
||||
</Tab>
|
||||
<Tab title="Python">
|
||||
```python
|
||||
current_page = 1
|
||||
has_more = True
|
||||
|
||||
while has_more:
|
||||
response = client.documents.list(page=current_page, limit=50)
|
||||
|
||||
print(f"Page {current_page}: {len(response.memories)} memories")
|
||||
|
||||
has_more = current_page < response.pagination.total_pages
|
||||
current_page += 1
|
||||
```
|
||||
</Tab>
|
||||
<Tab title="cURL">
|
||||
```bash
|
||||
# Manual pagination with bash loop
|
||||
for page in {1..5}; do
|
||||
echo "=== Page $page ==="
|
||||
curl -X POST "https://api.supermemory.ai/v3/documents/list" \
|
||||
-H "Authorization: Bearer $SUPERMEMORY_API_KEY" \
|
||||
-H "Content-Type: application/json" \
|
||||
-d "{\"page\": $page, \"limit\": 20}" | \
|
||||
jq '.memories | length'
|
||||
done
|
||||
```
|
||||
</Tab>
|
||||
</Tabs>
|
||||
|
||||
<Info>
|
||||
Use larger `limit` values (50-100) for pagination to reduce the number of API calls needed.
|
||||
</Info>
|
||||
|
|
@ -1,153 +0,0 @@
|
|||
---
|
||||
title: "List Memories"
|
||||
description: "Retrieve paginated memories with filtering and sorting options"
|
||||
sidebarTitle: "Overview"
|
||||
---
|
||||
|
||||
|
||||
Retrieve paginated memories with filtering and sorting options from your Supermemory account.
|
||||
|
||||
## Quick Start
|
||||
|
||||
<Tabs>
|
||||
<Tab title="TypeScript">
|
||||
```typescript
|
||||
import Supermemory from 'supermemory';
|
||||
|
||||
const client = new Supermemory({
|
||||
apiKey: process.env.SUPERMEMORY_API_KEY!
|
||||
});
|
||||
|
||||
const memories = await client.documents.list({ limit: 10 });
|
||||
console.log(memories);
|
||||
```
|
||||
</Tab>
|
||||
<Tab title="Python">
|
||||
```python
|
||||
from supermemory import Supermemory
|
||||
import os
|
||||
|
||||
client = Supermemory(api_key=os.environ.get("SUPERMEMORY_API_KEY"))
|
||||
memories = client.documents.list(limit=10)
|
||||
print(f"Found {len(memories.memories)} memories")
|
||||
```
|
||||
</Tab>
|
||||
<Tab title="cURL">
|
||||
```bash
|
||||
curl -X POST "https://api.supermemory.ai/v3/documents/list" \
|
||||
-H "Authorization: Bearer $SUPERMEMORY_API_KEY" \
|
||||
-H "Content-Type: application/json" \
|
||||
-d '{"limit": 10}'
|
||||
```
|
||||
</Tab>
|
||||
</Tabs>
|
||||
|
||||
## Response Schema
|
||||
|
||||
The endpoint returns a structured response containing your memories and pagination information:
|
||||
|
||||
```json
|
||||
{
|
||||
"memories": [
|
||||
{
|
||||
"id": "abc123",
|
||||
"connectionId": null,
|
||||
"createdAt": "2024-01-15T10:30:00.000Z",
|
||||
"updatedAt": "2024-01-15T10:35:00.000Z",
|
||||
"customId": "ml-basics-001",
|
||||
"title": "Introduction to Machine Learning",
|
||||
"summary": "This document introduces machine learning as a subset of artificial intelligence...",
|
||||
"status": "done",
|
||||
"type": "text",
|
||||
"metadata": {
|
||||
"category": "education",
|
||||
"priority": "high",
|
||||
"source": "research-notes"
|
||||
},
|
||||
"containerTags": ["user_123", "ai-research"]
|
||||
}
|
||||
],
|
||||
"pagination": {
|
||||
"currentPage": 1,
|
||||
"totalPages": 3,
|
||||
"totalItems": 25,
|
||||
"limit": 10
|
||||
}
|
||||
}
|
||||
```
|
||||
|
||||
### Memory Object Fields
|
||||
|
||||
<Accordion title="Core Fields" defaultOpen>
|
||||
|
||||
| Field | Type | Description |
|
||||
|-------|------|-------------|
|
||||
| `id` | string | Unique identifier for the memory |
|
||||
| `status` | ProcessingStatus | Current processing status (`queued`, `extracting`, `chunking`, `embedding`, `indexing`, `done`, `failed`) |
|
||||
| `type` | MemoryType | Content type (`text`, `pdf`, `webpage`, `video`, `image`, etc.) |
|
||||
| `title` | string \| null | Auto-generated or custom title |
|
||||
| `summary` | string \| null | AI-generated summary of content |
|
||||
| `createdAt` | string | ISO 8601 creation timestamp |
|
||||
| `updatedAt` | string | ISO 8601 last update timestamp |
|
||||
|
||||
</Accordion>
|
||||
|
||||
<Accordion title="Optional Fields">
|
||||
|
||||
| Field | Type | Description |
|
||||
|-------|------|-------------|
|
||||
| `customId` | string \| null | Your custom identifier for the memory |
|
||||
| `connectionId` | string \| null | ID of connector that created this memory |
|
||||
| `metadata` | object \| null | Custom key-value metadata you provided |
|
||||
| `containerTags` | string[] | Tags for organizing and filtering memories |
|
||||
|
||||
</Accordion>
|
||||
|
||||
## Key Parameters
|
||||
|
||||
All parameters are optional and sent in the request body since this endpoint uses `POST`:
|
||||
|
||||
<ParamField path="limit" type="number/string" default="50">
|
||||
**Number of items per page.** Controls how many memories are returned in a single request. Maximum recommended: 200 for optimal performance.
|
||||
</ParamField>
|
||||
|
||||
<ParamField path="page" type="number/string" default="1">
|
||||
**Page number to fetch (1-indexed).** Use with `limit` to paginate through large result sets.
|
||||
</ParamField>
|
||||
|
||||
<ParamField path="containerTags" type="string[]">
|
||||
**Filter by tags.** Memories must match ALL provided tags. Use for filtering by user ID, project, or custom organization tags.
|
||||
</ParamField>
|
||||
|
||||
<ParamField path="sort" type="string" default="createdAt">
|
||||
**Sort field.** Options: `"createdAt"` (when memory was added) or `"updatedAt"` (when memory was last modified).
|
||||
</ParamField>
|
||||
|
||||
<ParamField path="order" type="string" default="desc">
|
||||
**Sort direction.** Use `"desc"` for newest first, `"asc"` for oldest first.
|
||||
</ParamField>
|
||||
|
||||
<ParamField path="filters" type="string">
|
||||
**Advanced filtering.** Filter based on metadata with advanced SQL logic.
|
||||
</ParamField>
|
||||
|
||||
## Examples
|
||||
|
||||
<CardGroup cols={2}>
|
||||
<Card title="Basic Listing" icon="list" href="/list-memories/examples/basic">
|
||||
Simple memory retrieval with default settings
|
||||
</Card>
|
||||
<Card title="Filtering" icon="filter" href="/list-memories/examples/filtering">
|
||||
Filter by tags, status, and other criteria
|
||||
</Card>
|
||||
<Card title="Pagination" icon="arrow-right" href="/list-memories/examples/pagination">
|
||||
Handle large datasets with pagination
|
||||
</Card>
|
||||
<Card title="Status Monitoring" icon="chart-line" href="/list-memories/examples/monitoring">
|
||||
Track processing status across memories
|
||||
</Card>
|
||||
</CardGroup>
|
||||
|
||||
<Note>
|
||||
The `/v3/documents/list` endpoint uses **POST** method, not GET. This allows for complex filtering parameters in the request body.
|
||||
</Note>
|
||||
|
|
@ -6,7 +6,7 @@ icon: "database"
|
|||
---
|
||||
|
||||
<Info>
|
||||
These v4 endpoints operate on extracted memories (not raw documents). SDK support coming soon — use fetch or cURL for now.
|
||||
These v4 endpoints operate on extracted memories (not raw documents). The SDK already covers the v4 read surface — `client.search.memories` and `client.profile` — while the memory create/update/forget endpoints on this page are called with fetch or cURL for now.
|
||||
|
||||
For document management (list, get, update, delete), see [Document Operations](/document-operations).
|
||||
For ingesting raw content (text, files, URLs) through the processing pipeline, see [Add Context](/add-memories).
|
||||
|
|
|
|||
|
|
@ -15,7 +15,7 @@ inferred memories awaiting review, then **approve**, **decline**, or **undo** a
|
|||
decision on each one.
|
||||
|
||||
<Info>
|
||||
These endpoints are scoped to a single [container tag](/concepts/container-tags)
|
||||
These endpoints are scoped to a single [container tag](/concepts/permissioning)
|
||||
(space), under `/v3/container-tags/{containerTag}`.
|
||||
</Info>
|
||||
|
||||
|
|
|
|||
|
|
@ -38,7 +38,7 @@ for memory in data["memories"]:
|
|||
if memory.get("content"):
|
||||
supermemory.memories.add(
|
||||
content=memory["content"],
|
||||
container_tags=["imported_from_mem0"]
|
||||
container_tag="imported_from_mem0"
|
||||
)
|
||||
print(f"✅ {memory['content'][:50]}...")
|
||||
|
||||
|
|
@ -142,7 +142,7 @@ print("Migration complete!")
|
|||
try:
|
||||
result = client.add(
|
||||
content=content,
|
||||
container_tags=["imported_from_mem0"],
|
||||
container_tag="imported_from_mem0",
|
||||
metadata={
|
||||
"source": "mem0",
|
||||
"created_at": memory.get("created_at"),
|
||||
|
|
@ -182,7 +182,7 @@ from supermemory import Supermemory
|
|||
client = Supermemory(api_key="...")
|
||||
client.add(
|
||||
content="User prefers dark mode",
|
||||
container_tags=["user_alice"]
|
||||
container_tag="user_alice"
|
||||
)
|
||||
```
|
||||
|
||||
|
|
@ -200,9 +200,9 @@ results = client.search(
|
|||
```
|
||||
|
||||
```python Supermemory
|
||||
results = client.documents.search(
|
||||
query="user preferences",
|
||||
container_tags=["user_alice"]
|
||||
results = client.search.memories(
|
||||
q="user preferences",
|
||||
container_tag="user_alice"
|
||||
)
|
||||
```
|
||||
|
||||
|
|
@ -247,6 +247,6 @@ For enterprise migrations, [contact us](mailto:support@supermemory.ai) for assis
|
|||
|
||||
## Next Steps
|
||||
|
||||
1. [Explore](/how-it-works) how Supermemory works
|
||||
1. [Explore](/concepts/how-it-works) how Supermemory works
|
||||
2. Read the [quickstart](/quickstart) and add and retrieve your first memories
|
||||
3. [Connect](/connectors/overview) to Google Drive, Notion, and OneDrive with automatic syncing
|
||||
|
|
|
|||
|
|
@ -9,9 +9,9 @@ sidebarTitle: "From Zep"
|
|||
| Zep AI | Supermemory |
|
||||
|--------|-------------|
|
||||
| Sessions & Messages | Documents & Container Tags |
|
||||
| `session.create()` | Use `containerTags` parameter |
|
||||
| `memory.add(session_id, ...)` | `add({containerTag: [...]})` |
|
||||
| `memory.search(session_id, {text: ...})` | `search.execute({q: ..., containerTags: [...]})` |
|
||||
| `session.create()` | Use `containerTag` parameter |
|
||||
| `memory.add(session_id, ...)` | `add({containerTag: "..."})` |
|
||||
| `memory.search(session_id, {text: ...})` | `search.memories({q: ..., containerTag: "..."})` |
|
||||
|
||||
## Installation
|
||||
|
||||
|
|
@ -56,7 +56,7 @@ session = client.session.create(
|
|||
|
||||
```python Supermemory
|
||||
# No explicit session creation - use containerTag
|
||||
containerTag = ["user_123"]
|
||||
containerTag = "user_123"
|
||||
```
|
||||
|
||||
</CodeGroup>
|
||||
|
|
@ -75,7 +75,7 @@ client.memory.add(
|
|||
```python Supermemory
|
||||
client.add({
|
||||
"content": "User prefers dark mode",
|
||||
"containerTag": ["user_123"]
|
||||
"containerTag": "user_123"
|
||||
})
|
||||
```
|
||||
|
||||
|
|
@ -93,9 +93,9 @@ results = client.memory.search(
|
|||
```
|
||||
|
||||
```python Supermemory
|
||||
results = client.search.execute({
|
||||
results = client.search.memories({
|
||||
"q": "preferences",
|
||||
"containerTag": ["user_123"],
|
||||
"containerTag": "user_123",
|
||||
"limit": 5
|
||||
})
|
||||
```
|
||||
|
|
@ -112,7 +112,7 @@ memories = client.memory.get(session_id="user_123")
|
|||
|
||||
```python Supermemory
|
||||
documents = client.documents.list({
|
||||
"containerTag": ["user_123"],
|
||||
"containerTags": ["user_123"],
|
||||
"limit": 100
|
||||
})
|
||||
```
|
||||
|
|
@ -122,8 +122,8 @@ documents = client.documents.list({
|
|||
## Migration Steps
|
||||
|
||||
1. **Replace client initialization** - Use Supermemory client instead of Zep
|
||||
2. **Map sessions to container tags** - Replace `session_id="user_123"` with `containerTag: ["user_123"]`
|
||||
3. **Update method calls** - Use `add()` and `search.execute()` instead of `memory.add()` and `memory.search()`
|
||||
2. **Map sessions to container tags** - Replace `session_id="user_123"` with `containerTag: "user_123"`
|
||||
3. **Update method calls** - Use `add()` and `search.memories()` instead of `memory.add()` and `memory.search()`
|
||||
4. **Change search parameter** - Use `q` instead of `text`
|
||||
5. **Handle async processing** - Documents process asynchronously (status: `queued` → `done`)
|
||||
|
||||
|
|
@ -152,7 +152,7 @@ results = client.memory.search("user_123", {
|
|||
from supermemory import Supermemory
|
||||
|
||||
client = Supermemory(api_key="...")
|
||||
containerTag = ["user_123"]
|
||||
containerTag = "user_123"
|
||||
|
||||
client.add({
|
||||
"content": "I love Python",
|
||||
|
|
@ -160,7 +160,7 @@ client.add({
|
|||
"metadata": {"role": "user"}
|
||||
})
|
||||
|
||||
results = client.search.execute({
|
||||
results = client.search.memories({
|
||||
"q": "programming",
|
||||
"containerTag": containerTag,
|
||||
"limit": 3
|
||||
|
|
@ -203,10 +203,11 @@ for (const sessionId of sessionIds) {
|
|||
if (mem.content) {
|
||||
await supermemory.add({
|
||||
content: mem.content,
|
||||
containerTag: [`session_${sessionId}`, `user_${memory.user_id || "unknown"}`],
|
||||
containerTag: `user_${memory.user_id || "unknown"}`,
|
||||
metadata: {
|
||||
role: mem.role,
|
||||
type: "message",
|
||||
session_id: sessionId,
|
||||
original_uuid: mem.uuid,
|
||||
...mem.metadata
|
||||
}
|
||||
|
|
@ -238,10 +239,11 @@ for session_id in session_ids:
|
|||
if mem.content:
|
||||
supermemory.add({
|
||||
"content": mem.content,
|
||||
"containerTag": [f"session_{session_id}", f"user_{memory.user_id or 'unknown'}"],
|
||||
"containerTag": f"user_{memory.user_id or 'unknown'}",
|
||||
"metadata": {
|
||||
"role": mem.role,
|
||||
"type": "message",
|
||||
"session_id": session_id,
|
||||
"original_uuid": mem.uuid,
|
||||
**(mem.metadata or {})
|
||||
}
|
||||
|
|
@ -315,10 +317,9 @@ async function migrateFromZep(
|
|||
// Import to Supermemory
|
||||
let totalMemories = 0;
|
||||
for (const [sessionId, data] of Object.entries(exportedData) as any) {
|
||||
const containerTag = ["imported_from_zep", `session_${sessionId}`];
|
||||
if (data.session.user_id) {
|
||||
containerTag.push(`user_${data.session.user_id}`);
|
||||
}
|
||||
const containerTag = data.session.user_id
|
||||
? `user_${data.session.user_id}`
|
||||
: `session_${sessionId}`;
|
||||
|
||||
for (const memory of data.memories) {
|
||||
totalMemories++;
|
||||
|
|
@ -335,6 +336,7 @@ async function migrateFromZep(
|
|||
source: "zep_migration",
|
||||
role: memory.role,
|
||||
type: "message",
|
||||
session_id: sessionId,
|
||||
original_uuid: memory.uuid,
|
||||
...memory.metadata,
|
||||
},
|
||||
|
|
@ -368,5 +370,5 @@ migrateFromZep(
|
|||
## Resources
|
||||
|
||||
- [Supermemory SDKs](/integrations/supermemory-sdk)
|
||||
- [API Reference](/memory-api/overview)
|
||||
- [API Reference](/add-memories)
|
||||
- [Search Documentation](/search)
|
||||
|
|
|
|||
|
|
@ -34,7 +34,7 @@ npm install @supermemory/tools@^2.0.0
|
|||
// v1.4.x
|
||||
import { withSupermemory } from '@supermemory/tools/ai-sdk';
|
||||
|
||||
const model = withSupermemory(openai('gpt-4'), 'user-123', {
|
||||
const model = withSupermemory(openai('gpt-4o'), 'user-123', {
|
||||
conversationId: 'conv-456',
|
||||
mode: 'full',
|
||||
});
|
||||
|
|
@ -44,7 +44,7 @@ const model = withSupermemory(openai('gpt-4'), 'user-123', {
|
|||
// v2.0.0
|
||||
import { withSupermemory } from '@supermemory/tools/ai-sdk';
|
||||
|
||||
const model = withSupermemory(openai('gpt-4'), {
|
||||
const model = withSupermemory(openai('gpt-4o'), {
|
||||
containerTag: 'user-123',
|
||||
customId: 'conv-456',
|
||||
mode: 'full',
|
||||
|
|
@ -139,7 +139,7 @@ If you were relying on `verbose: false` implicitly while passing `verbose: true`
|
|||
Across all four integrations, `addMemory` now defaults to `"always"`. If your v1.4.x code relied on the old default of `"never"`, set it explicitly:
|
||||
|
||||
```typescript
|
||||
const model = withSupermemory(openai('gpt-4'), {
|
||||
const model = withSupermemory(openai('gpt-4o'), {
|
||||
containerTag: 'user-123',
|
||||
customId: 'conv-456',
|
||||
addMemory: 'never', // preserve v1.4.x behavior
|
||||
|
|
|
|||
|
|
@ -1,92 +0,0 @@
|
|||
---
|
||||
title: "n8n Integration"
|
||||
description: "Automate knowledge management with Supermemory in n8n workflows"
|
||||
sidebarTitle: "n8n"
|
||||
---
|
||||
|
||||
Connect Supermemory to your n8n workflows to build intelligent automation workflows and agents that leverage your full knowledge base.
|
||||
|
||||
## Quick Start
|
||||
|
||||
### Prerequisites
|
||||
|
||||
- n8n instance (self-hosted or cloud)
|
||||
- Supermemory API key ([get one here](https://console.supermemory.ai/settings))
|
||||
- Basic understanding of n8n workflows
|
||||
|
||||
### Setting Up the HTTP Request Node
|
||||
|
||||
The Supermemory integration in n8n uses the HTTP Request node to interact with the Supermemory API. Here's how to configure it:
|
||||
|
||||
1. Add an **HTTP Request** node to your workflow (Core > HTTP Request)
|
||||

|
||||
2. Set the **Method** to `POST`
|
||||
3. Set the **URL** to the appropriate Supermemory API endpoint:
|
||||
- Add memory: `https://api.supermemory.ai/v3/documents`
|
||||
- Search memories: `https://api.supermemory.ai/v4/search`
|
||||
4. For authentication, select **Generic Credential Type** and then **Bearer Auth**
|
||||
5. Click on **Create New Credential** and paste the Supermemory API Key in the Bearer Token field.
|
||||

|
||||
6. Check **Send Body** and select **JSON** as the Body Content Type. The fields depend on what API endpoint you're sending the request to. You can find detailed step-by-step examples below.
|
||||
|
||||
## Step-by-Step Tutorial
|
||||
|
||||
In this tutorial, we'll create a workflow that automatically adds every email from Gmail to your Supermemory knowledge base. We'll use the HTTP Request node to send email data to Supermemory's API, creating a searchable archive of all your communications.
|
||||
|
||||
### Adding Gmail Emails to Supermemory
|
||||
|
||||
Follow these steps to build a workflow that captures and stores your Gmail messages:
|
||||
|
||||
#### Step 1: Set Up Gmail Trigger
|
||||
|
||||

|
||||
|
||||
1. **Add a Gmail Trigger node** to your workflow
|
||||
2. Configure your Gmail credentials (OAuth2 recommended)
|
||||
3. Set the trigger to **Message Received**
|
||||
4. Optional: Add labels or filters to process specific emails only
|
||||
|
||||
#### Step 2: Configure HTTP Request Node
|
||||
|
||||
1. **Add an HTTP Request node** after the Gmail Trigger
|
||||
2. **Method**: `POST`
|
||||
3. **URL**: `https://api.supermemory.ai/v3/documents`
|
||||
4. Select your auth credentials you created with the Supermemory API Key.
|
||||
|
||||
#### Step 3: Format Email Data for Supermemory
|
||||
|
||||
In the HTTP Request node's **Body**, select **JSON** and **Using Fields Below**
|
||||
|
||||
And create 2 fields:
|
||||
|
||||
1. name: `content`, value: `{{ $json.snippet }}`
|
||||
2. name: `containerTag`, value: gmail
|
||||
|
||||
|
||||

|
||||
|
||||
#### Step 4: Handle Attachments (Optional)
|
||||
|
||||
If you want to process attachments:
|
||||
|
||||
1. **Add a Loop node** after the Gmail Trigger
|
||||
2. Loop through `{{$json.attachments}}`
|
||||
3. **Add a Gmail node** to download each attachment
|
||||
4. **Add another HTTP Request node** to store attachment metadata
|
||||
|
||||
|
||||
#### Step 5: Add Error Handling
|
||||
|
||||
1. **Add an Error Trigger node** connected to your workflow
|
||||
2. Configure it to catch errors from the HTTP Request node
|
||||
3. **Add a notification node** (Email, Slack, etc.) to alert you of failures
|
||||
4. Optional: Add a **Wait node** with retry logic
|
||||
|
||||
#### Step 6: Test Your Workflow
|
||||
|
||||
1. **Activate the workflow** in test mode
|
||||
2. Send a test email to your Gmail account
|
||||
3. Check the execution to ensure the email was captured
|
||||
4. Verify in Supermemory that the email appears in search results
|
||||
|
||||
Refer to the API Reference tab to learn more about other supermemory API endpoints.
|
||||
|
|
@ -165,7 +165,7 @@ const results = await client.search.memories({
|
|||
- **Array contains:** `{ filterType: "array_contains", key: "tags", value: "important" }`
|
||||
- **Negate:** `{ key: "status", value: "draft", negate: true }`
|
||||
|
||||
See [Organizing & Filtering](/concepts/filtering) for full syntax.
|
||||
See [Organizing & Filtering](/concepts/hybrid-search) for full syntax.
|
||||
</Accordion>
|
||||
|
||||
---
|
||||
|
|
@ -244,4 +244,4 @@ async function getContext(userId: string, message: string) {
|
|||
|
||||
- [Ingesting Content](/add-memories) — Add content to search
|
||||
- [User Profiles](/user-profiles) — Get user context with search
|
||||
- [Organizing & Filtering](/concepts/filtering) — Container tags and metadata
|
||||
- [Organizing & Filtering](/concepts/hybrid-search) — Container tags and metadata
|
||||
|
|
|
|||
|
|
@ -1,588 +0,0 @@
|
|||
---
|
||||
title: "Documents Search (/v3/search)"
|
||||
description: "Full-featured search with extensive control over ranking, filtering, and results"
|
||||
---
|
||||
|
||||
Documents search (`POST /v3/search`) provides maximum control over search behavior with extensive parameters for fine-tuning results.
|
||||
|
||||
## Basic Implementation
|
||||
|
||||
<Tabs>
|
||||
<Tab title="TypeScript">
|
||||
```typescript
|
||||
import Supermemory from 'supermemory';
|
||||
|
||||
const client = new Supermemory({
|
||||
apiKey: process.env.SUPERMEMORY_API_KEY!
|
||||
});
|
||||
|
||||
const results = await client.search.documents({
|
||||
q: "machine learning neural networks",
|
||||
limit: 5
|
||||
});
|
||||
|
||||
console.log(`Found ${results.total} documents in ${results.timing}ms`);
|
||||
|
||||
// Sample output structure
|
||||
results.results.forEach((doc, i) => {
|
||||
console.log(`${i + 1}. ${doc.title} (Score: ${doc.score})`);
|
||||
console.log(` ${doc.chunks.length} chunks found`);
|
||||
});
|
||||
```
|
||||
</Tab>
|
||||
<Tab title="Python">
|
||||
```python
|
||||
from supermemory import Supermemory
|
||||
import os
|
||||
|
||||
client = Supermemory(api_key=os.environ.get("SUPERMEMORY_API_KEY"))
|
||||
|
||||
results = client.search.documents(
|
||||
q="machine learning neural networks",
|
||||
limit=5
|
||||
)
|
||||
|
||||
print(f"Found {results.total} documents in {results.timing}ms")
|
||||
|
||||
# Sample output structure
|
||||
for i, doc in enumerate(results.results):
|
||||
print(f"{i + 1}. {doc.title} (Score: {doc.score})")
|
||||
print(f" {len(doc.chunks)} chunks found")
|
||||
```
|
||||
</Tab>
|
||||
<Tab title="cURL">
|
||||
```bash
|
||||
curl -X POST "https://api.supermemory.ai/v3/search" \
|
||||
-H "Authorization: Bearer $SUPERMEMORY_API_KEY" \
|
||||
-H "Content-Type: application/json" \
|
||||
-d '{
|
||||
"q": "machine learning neural networks",
|
||||
"limit": 5
|
||||
}'
|
||||
```
|
||||
</Tab>
|
||||
</Tabs>
|
||||
|
||||
**Sample Output:**
|
||||
```json
|
||||
{
|
||||
"results": [
|
||||
{
|
||||
"documentId": "doc_ml_guide_2024",
|
||||
"title": "Machine Learning with Neural Networks: A Comprehensive Guide",
|
||||
"score": 0.89,
|
||||
"chunks": [
|
||||
{
|
||||
"content": "Neural networks are computational models inspired by biological neural networks. They consist of interconnected nodes (neurons) that process information through weighted connections...",
|
||||
"score": 0.92,
|
||||
"isRelevant": true
|
||||
},
|
||||
{
|
||||
"content": "Deep learning, a subset of machine learning, uses neural networks with multiple hidden layers to learn complex patterns in data...",
|
||||
"score": 0.87,
|
||||
"isRelevant": true
|
||||
}
|
||||
],
|
||||
"createdAt": "2024-01-15T10:30:00Z",
|
||||
"metadata": {
|
||||
"category": "ai",
|
||||
"difficulty": "intermediate"
|
||||
}
|
||||
}
|
||||
],
|
||||
"total": 12,
|
||||
"timing": 156
|
||||
}
|
||||
```
|
||||
|
||||
## Container Tags Filtering
|
||||
|
||||
Container tags are the primary way to isolate search results by user, project, or organization.
|
||||
|
||||
**Key behaviors:**
|
||||
- **Array-based**: Unlike `/v4/search`, this endpoint accepts multiple container tags as an array
|
||||
- **Exact array matching**: Documents must have the EXACT same container tags array to match
|
||||
|
||||
<Tabs>
|
||||
<Tab title="TypeScript">
|
||||
```typescript
|
||||
const results = await client.search.documents({
|
||||
q: "quarterly reports",
|
||||
containerTags: ["user_123"],
|
||||
limit: 10
|
||||
});
|
||||
```
|
||||
</Tab>
|
||||
<Tab title="Python">
|
||||
```python
|
||||
results = client.search.documents(
|
||||
q="quarterly reports",
|
||||
container_tags=["user_123"],
|
||||
limit=10
|
||||
)
|
||||
```
|
||||
</Tab>
|
||||
<Tab title="cURL">
|
||||
```bash
|
||||
curl -X POST "https://api.supermemory.ai/v3/search" \
|
||||
-H "Authorization: Bearer $SUPERMEMORY_API_KEY" \
|
||||
-H "Content-Type: application/json" \
|
||||
-d '{
|
||||
"q": "quarterly reports",
|
||||
"containerTags": ["user_123"],
|
||||
"limit": 10
|
||||
}'
|
||||
```
|
||||
</Tab>
|
||||
</Tabs>
|
||||
|
||||
## Metadata Filtering
|
||||
|
||||
Metadata filtering allows complex conditions on structured data attached to your documents. This uses SQL-like query construction in the backend, requiring explicit AND/OR structures.
|
||||
|
||||
**Filter structure rules:**
|
||||
- **Must wrap conditions** in AND or OR arrays, even for single conditions
|
||||
- **Supports string matching** (exact), numeric operators, and array contains
|
||||
- **Negate any condition** with `negate: true`
|
||||
- **Combines with container tags** - both filters are applied
|
||||
|
||||
<Tabs>
|
||||
<Tab title="TypeScript">
|
||||
```typescript
|
||||
const results = await client.search.documents({
|
||||
q: "machine learning",
|
||||
filters: {
|
||||
AND: [
|
||||
{
|
||||
key: "category",
|
||||
value: "technology",
|
||||
negate: false
|
||||
},
|
||||
{
|
||||
filterType: "numeric",
|
||||
key: "readingTime",
|
||||
value: "5",
|
||||
negate: false,
|
||||
numericOperator: "<="
|
||||
}
|
||||
]
|
||||
},
|
||||
limit: 10
|
||||
});
|
||||
```
|
||||
</Tab>
|
||||
<Tab title="Python">
|
||||
```python
|
||||
results = client.search.documents(
|
||||
q="machine learning",
|
||||
filters={
|
||||
"AND": [
|
||||
{
|
||||
"key": "category",
|
||||
"value": "technology",
|
||||
"negate": False
|
||||
},
|
||||
{
|
||||
"filterType": "numeric",
|
||||
"key": "readingTime",
|
||||
"value": "5",
|
||||
"negate": False,
|
||||
"numericOperator": "<="
|
||||
}
|
||||
]
|
||||
},
|
||||
limit=10
|
||||
)
|
||||
```
|
||||
</Tab>
|
||||
<Tab title="cURL">
|
||||
```bash
|
||||
curl -X POST "https://api.supermemory.ai/v3/search" \
|
||||
-H "Authorization: Bearer $SUPERMEMORY_API_KEY" \
|
||||
-H "Content-Type: application/json" \
|
||||
-d '{
|
||||
"q": "machine learning",
|
||||
"filters": {
|
||||
"AND": [
|
||||
{
|
||||
"key": "category",
|
||||
"value": "technology",
|
||||
"negate": false
|
||||
},
|
||||
{
|
||||
"filterType": "numeric",
|
||||
"key": "readingTime",
|
||||
"value": "5",
|
||||
"negate": false,
|
||||
"numericOperator": "<="
|
||||
}
|
||||
]
|
||||
},
|
||||
"limit": 10
|
||||
}'
|
||||
```
|
||||
</Tab>
|
||||
</Tabs>
|
||||
|
||||
**Sample Output:**
|
||||
```json
|
||||
{
|
||||
"results": [
|
||||
{
|
||||
"documentId": "doc_tech_trends_2024",
|
||||
"title": "Technology Trends in Machine Learning",
|
||||
"score": 0.91,
|
||||
"chunks": [
|
||||
{
|
||||
"content": "Machine learning continues to evolve with new architectures and optimization techniques. Reading time for this comprehensive overview is approximately 8 minutes...",
|
||||
"score": 0.88,
|
||||
"isRelevant": true
|
||||
}
|
||||
],
|
||||
"metadata": {
|
||||
"category": "technology",
|
||||
"readingTime": 8,
|
||||
"difficulty": "intermediate",
|
||||
"published": true
|
||||
}
|
||||
}
|
||||
],
|
||||
"total": 6,
|
||||
"timing": 189
|
||||
}
|
||||
```
|
||||
|
||||
## Array Contains Filtering
|
||||
|
||||
When your metadata includes arrays (like participant lists, tags, or categories), use `array_contains` to check if the array includes a specific value.
|
||||
|
||||
<Tabs>
|
||||
<Tab title="TypeScript">
|
||||
```typescript
|
||||
const results = await client.search.documents({
|
||||
q: "meeting discussion",
|
||||
filters: {
|
||||
AND: [
|
||||
{
|
||||
key: "participants",
|
||||
value: "john.doe",
|
||||
filterType: "array_contains"
|
||||
}
|
||||
]
|
||||
},
|
||||
limit: 5
|
||||
});
|
||||
```
|
||||
</Tab>
|
||||
<Tab title="Python">
|
||||
```python
|
||||
results = client.search.documents(
|
||||
q="meeting discussion",
|
||||
filters={
|
||||
"AND": [
|
||||
{
|
||||
"key": "participants",
|
||||
"value": "john.doe",
|
||||
"filterType": "array_contains"
|
||||
}
|
||||
]
|
||||
},
|
||||
limit=5
|
||||
)
|
||||
```
|
||||
</Tab>
|
||||
<Tab title="cURL">
|
||||
```bash
|
||||
curl -X POST "https://api.supermemory.ai/v3/search" \
|
||||
-H "Authorization: Bearer $SUPERMEMORY_API_KEY" \
|
||||
-H "Content-Type: application/json" \
|
||||
-d '{
|
||||
"q": "meeting discussion",
|
||||
"filters": {
|
||||
"AND": [
|
||||
{
|
||||
"key": "participants",
|
||||
"value": "john.doe",
|
||||
"filterType": "array_contains"
|
||||
}
|
||||
]
|
||||
},
|
||||
"limit": 5
|
||||
}'
|
||||
```
|
||||
</Tab>
|
||||
</Tabs>
|
||||
|
||||
## Threshold Control
|
||||
|
||||
Control result quality with sensitivity thresholds:
|
||||
|
||||
<Tabs>
|
||||
<Tab title="TypeScript">
|
||||
```typescript
|
||||
const results = await client.search.documents({
|
||||
q: "artificial intelligence",
|
||||
documentThreshold: 0.7, // Higher = fewer, more relevant documents
|
||||
chunkThreshold: 0.8, // Higher = fewer, more relevant chunks
|
||||
limit: 10
|
||||
});
|
||||
```
|
||||
</Tab>
|
||||
<Tab title="Python">
|
||||
```python
|
||||
results = client.search.documents(
|
||||
q="artificial intelligence",
|
||||
document_threshold=0.7, # Higher = fewer, more relevant documents
|
||||
chunk_threshold=0.8, # Higher = fewer, more relevant chunks
|
||||
limit=10
|
||||
)
|
||||
```
|
||||
</Tab>
|
||||
<Tab title="cURL">
|
||||
```bash
|
||||
curl -X POST "https://api.supermemory.ai/v3/search" \
|
||||
-H "Authorization: Bearer $SUPERMEMORY_API_KEY" \
|
||||
-H "Content-Type: application/json" \
|
||||
-d '{
|
||||
"q": "artificial intelligence",
|
||||
"documentThreshold": 0.7,
|
||||
"chunkThreshold": 0.8,
|
||||
"limit": 10
|
||||
}'
|
||||
```
|
||||
</Tab>
|
||||
</Tabs>
|
||||
|
||||
## Query Rewriting
|
||||
|
||||
Improve search accuracy with automatic query rewriting:
|
||||
|
||||
<Tabs>
|
||||
<Tab title="TypeScript">
|
||||
```typescript
|
||||
const results = await client.search.documents({
|
||||
q: "What is the capital of France?",
|
||||
rewriteQuery: true, // +400ms latency but better results
|
||||
limit: 5
|
||||
});
|
||||
```
|
||||
</Tab>
|
||||
<Tab title="Python">
|
||||
```python
|
||||
results = client.search.documents(
|
||||
q="What is the capital of France?",
|
||||
rewrite_query=True, # +400ms latency but better results
|
||||
limit=5
|
||||
)
|
||||
```
|
||||
</Tab>
|
||||
<Tab title="cURL">
|
||||
```bash
|
||||
curl -X POST "https://api.supermemory.ai/v3/search" \
|
||||
-H "Authorization: Bearer $SUPERMEMORY_API_KEY" \
|
||||
-H "Content-Type: application/json" \
|
||||
-d '{
|
||||
"q": "What is the capital of France?",
|
||||
"rewriteQuery": true,
|
||||
"limit": 5
|
||||
}'
|
||||
```
|
||||
</Tab>
|
||||
</Tabs>
|
||||
|
||||
<Note>
|
||||
Query rewriting generates multiple query variations and searches through all of them, then merges results. No additional cost but adds ~400ms latency.
|
||||
</Note>
|
||||
|
||||
## Reranking
|
||||
|
||||
Improve result quality with secondary ranking:
|
||||
|
||||
<Tabs>
|
||||
<Tab title="TypeScript">
|
||||
```typescript
|
||||
const results = await client.search.documents({
|
||||
q: "machine learning applications",
|
||||
rerank: true, // Apply secondary ranking algorithm
|
||||
limit: 10
|
||||
});
|
||||
```
|
||||
</Tab>
|
||||
<Tab title="Python">
|
||||
```python
|
||||
results = client.search.documents(
|
||||
q="machine learning applications",
|
||||
rerank=True, # Apply secondary ranking algorithm
|
||||
limit=10
|
||||
)
|
||||
```
|
||||
</Tab>
|
||||
<Tab title="cURL">
|
||||
```bash
|
||||
curl -X POST "https://api.supermemory.ai/v3/search" \
|
||||
-H "Authorization: Bearer $SUPERMEMORY_API_KEY" \
|
||||
-H "Content-Type: application/json" \
|
||||
-d '{
|
||||
"q": "machine learning applications",
|
||||
"rerank": true,
|
||||
"limit": 10
|
||||
}'
|
||||
```
|
||||
</Tab>
|
||||
</Tabs>
|
||||
|
||||
## Document-Specific Search
|
||||
|
||||
Search within a specific large document:
|
||||
|
||||
<Tabs>
|
||||
<Tab title="TypeScript">
|
||||
```typescript
|
||||
const results = await client.search.documents({
|
||||
q: "neural networks",
|
||||
docId: "doc_123", // Search only within this document
|
||||
limit: 10
|
||||
});
|
||||
```
|
||||
</Tab>
|
||||
<Tab title="Python">
|
||||
```python
|
||||
results = client.search.documents(
|
||||
q="neural networks",
|
||||
doc_id="doc_123", # Search only within this document
|
||||
limit=10
|
||||
)
|
||||
```
|
||||
</Tab>
|
||||
<Tab title="cURL">
|
||||
```bash
|
||||
curl -X POST "https://api.supermemory.ai/v3/search" \
|
||||
-H "Authorization: Bearer $SUPERMEMORY_API_KEY" \
|
||||
-H "Content-Type: application/json" \
|
||||
-d '{
|
||||
"q": "neural networks",
|
||||
"docId": "doc_123",
|
||||
"limit": 10
|
||||
}'
|
||||
```
|
||||
</Tab>
|
||||
</Tabs>
|
||||
|
||||
## Full Context Options
|
||||
|
||||
Include complete document content and summaries:
|
||||
|
||||
<Tabs>
|
||||
<Tab title="TypeScript">
|
||||
```typescript
|
||||
const results = await client.search.documents({
|
||||
q: "research findings",
|
||||
includeFullDocs: true, // Include complete document content
|
||||
includeSummary: true, // Include document summaries
|
||||
onlyMatchingChunks: false, // Include all chunks, not just matching ones
|
||||
limit: 5
|
||||
});
|
||||
```
|
||||
</Tab>
|
||||
<Tab title="Python">
|
||||
```python
|
||||
results = client.search.documents(
|
||||
q="research findings",
|
||||
include_full_docs=True, # Include complete document content
|
||||
include_summary=True, # Include document summaries
|
||||
only_matching_chunks=False, # Include all chunks, not just matching ones
|
||||
limit=5
|
||||
)
|
||||
```
|
||||
</Tab>
|
||||
<Tab title="cURL">
|
||||
```bash
|
||||
curl -X POST "https://api.supermemory.ai/v3/search" \
|
||||
-H "Authorization: Bearer $SUPERMEMORY_API_KEY" \
|
||||
-H "Content-Type: application/json" \
|
||||
-d '{
|
||||
"q": "research findings",
|
||||
"includeFullDocs": true,
|
||||
"includeSummary": true,
|
||||
"onlyMatchingChunks": false,
|
||||
"limit": 5
|
||||
}'
|
||||
```
|
||||
</Tab>
|
||||
</Tabs>
|
||||
|
||||
## Complete Advanced Example
|
||||
|
||||
Combining all features for maximum control:
|
||||
|
||||
<Tabs>
|
||||
<Tab title="TypeScript">
|
||||
```typescript
|
||||
const results = await client.search.documents({
|
||||
q: "machine learning performance metrics",
|
||||
containerTags: ["research_project"],
|
||||
filters: {
|
||||
AND: [
|
||||
{ key: "category", value: "ai", negate: false },
|
||||
{ key: "status", value: "published", negate: false }
|
||||
]
|
||||
},
|
||||
documentThreshold: 0.6,
|
||||
chunkThreshold: 0.7,
|
||||
rewriteQuery: true,
|
||||
rerank: true,
|
||||
includeFullDocs: false,
|
||||
includeSummary: true,
|
||||
onlyMatchingChunks: true,
|
||||
limit: 10
|
||||
});
|
||||
```
|
||||
</Tab>
|
||||
<Tab title="Python">
|
||||
```python
|
||||
results = client.search.documents(
|
||||
q="machine learning performance metrics",
|
||||
container_tags=["research_project"],
|
||||
filters={
|
||||
"AND": [
|
||||
{"key": "category", "value": "ai", "negate": False},
|
||||
{"key": "status", "value": "published", "negate": False}
|
||||
]
|
||||
},
|
||||
document_threshold=0.6,
|
||||
chunk_threshold=0.7,
|
||||
rewrite_query=True,
|
||||
rerank=True,
|
||||
include_full_docs=False,
|
||||
include_summary=True,
|
||||
only_matching_chunks=True,
|
||||
limit=10
|
||||
)
|
||||
```
|
||||
</Tab>
|
||||
<Tab title="cURL">
|
||||
```bash
|
||||
curl -X POST "https://api.supermemory.ai/v3/search" \
|
||||
-H "Authorization: Bearer $SUPERMEMORY_API_KEY" \
|
||||
-H "Content-Type: application/json" \
|
||||
-d '{
|
||||
"q": "machine learning performance metrics",
|
||||
"containerTags": ["research_project"],
|
||||
"filters": {
|
||||
"AND": [
|
||||
{"key": "category", "value": "ai", "negate": false},
|
||||
{"key": "status", "value": "published", "negate": false}
|
||||
]
|
||||
},
|
||||
"documentThreshold": 0.6,
|
||||
"chunkThreshold": 0.7,
|
||||
"rewriteQuery": true,
|
||||
"rerank": true,
|
||||
"includeFullDocs": false,
|
||||
"includeSummary": true,
|
||||
"onlyMatchingChunks": true,
|
||||
"limit": 10
|
||||
}'
|
||||
```
|
||||
</Tab>
|
||||
</Tabs>
|
||||
|
|
@ -1,695 +0,0 @@
|
|||
---
|
||||
title: "Memories Search (/v4/search)"
|
||||
description: "Minimal-latency search optimized for chatbots and conversational AI"
|
||||
---
|
||||
|
||||
|
||||
Memories search (`POST /v4/search`) provides minimal-latency search optimized for real-time interactions. This endpoint prioritizes speed over extensive control, making it perfect for chatbots, Q&A systems, and any application where users expect immediate responses.
|
||||
|
||||
## Basic Search
|
||||
|
||||
<Tabs>
|
||||
<Tab title="TypeScript">
|
||||
```typescript
|
||||
import Supermemory from 'supermemory';
|
||||
|
||||
const client = new Supermemory({
|
||||
apiKey: process.env.SUPERMEMORY_API_KEY!
|
||||
});
|
||||
|
||||
const results = await client.search.memories({
|
||||
q: "machine learning applications",
|
||||
limit: 5
|
||||
});
|
||||
|
||||
console.log(results)
|
||||
```
|
||||
</Tab>
|
||||
<Tab title="Python">
|
||||
```python
|
||||
from supermemory import Supermemory
|
||||
import os
|
||||
|
||||
client = Supermemory(api_key=os.environ.get("SUPERMEMORY_API_KEY"))
|
||||
|
||||
results = client.search.memories(
|
||||
q="machine learning applications",
|
||||
limit=5
|
||||
)
|
||||
|
||||
console.log(results)
|
||||
```
|
||||
</Tab>
|
||||
<Tab title="cURL">
|
||||
```bash
|
||||
curl -X POST "https://api.supermemory.ai/v4/search" \
|
||||
-H "Authorization: Bearer $SUPERMEMORY_API_KEY" \
|
||||
-H "Content-Type: application/json" \
|
||||
-d '{
|
||||
"q": "machine learning applications",
|
||||
"limit": 5
|
||||
}'
|
||||
```
|
||||
</Tab>
|
||||
</Tabs>
|
||||
|
||||
**Sample Output:**
|
||||
```json
|
||||
{
|
||||
"results": [
|
||||
{
|
||||
"id": "mem_ml_apps_2024",
|
||||
"memory": "Machine learning applications span numerous industries including healthcare (diagnostic imaging, drug discovery), finance (fraud detection, algorithmic trading), autonomous vehicles (computer vision, path planning), and natural language processing (chatbots, translation services).",
|
||||
"similarity": 0.92,
|
||||
"title": "Machine Learning Industry Applications",
|
||||
"type": "text",
|
||||
"metadata": {
|
||||
"topic": "machine-learning",
|
||||
"industry": "technology",
|
||||
"created": "2024-01-10"
|
||||
}
|
||||
},
|
||||
{
|
||||
"id": "mem_ml_healthcare",
|
||||
"memory": "In healthcare, machine learning enables early disease detection through medical imaging analysis, personalized treatment recommendations, and drug discovery acceleration by predicting molecular behavior.",
|
||||
"similarity": 0.89,
|
||||
"title": "ML in Healthcare",
|
||||
"type": "text"
|
||||
}
|
||||
],
|
||||
"total": 8,
|
||||
"timing": 87
|
||||
}
|
||||
```
|
||||
|
||||
## Container Tag Filtering
|
||||
|
||||
Filter by user, project, or organization:
|
||||
|
||||
<Tabs>
|
||||
<Tab title="TypeScript">
|
||||
```typescript
|
||||
const results = await client.search.memories({
|
||||
q: "project updates",
|
||||
containerTag: "user_123", // Note: singular, not plural
|
||||
limit: 10
|
||||
});
|
||||
```
|
||||
</Tab>
|
||||
<Tab title="Python">
|
||||
```python
|
||||
results = client.search.memories(
|
||||
q="project updates",
|
||||
container_tag="user_123", # Note: singular, not plural
|
||||
limit=10
|
||||
)
|
||||
```
|
||||
</Tab>
|
||||
<Tab title="cURL">
|
||||
```bash
|
||||
curl -X POST "https://api.supermemory.ai/v4/search" \
|
||||
-H "Authorization: Bearer $SUPERMEMORY_API_KEY" \
|
||||
-H "Content-Type: application/json" \
|
||||
-d '{
|
||||
"q": "project updates",
|
||||
"containerTag": "user_123",
|
||||
"limit": 10
|
||||
}'
|
||||
```
|
||||
</Tab>
|
||||
</Tabs>
|
||||
|
||||
## Threshold Control
|
||||
|
||||
Control result quality with similarity threshold:
|
||||
|
||||
<Tabs>
|
||||
<Tab title="TypeScript">
|
||||
```typescript
|
||||
const results = await client.search.memories({
|
||||
q: "artificial intelligence research",
|
||||
threshold: 0.7, // Higher = fewer, more similar results
|
||||
limit: 10
|
||||
});
|
||||
```
|
||||
</Tab>
|
||||
<Tab title="Python">
|
||||
```python
|
||||
results = client.search.memories(
|
||||
q="artificial intelligence research",
|
||||
threshold=0.7, # Higher = fewer, more similar results
|
||||
limit=10
|
||||
)
|
||||
```
|
||||
</Tab>
|
||||
<Tab title="cURL">
|
||||
```bash
|
||||
curl -X POST "https://api.supermemory.ai/v4/search" \
|
||||
-H "Authorization: Bearer $SUPERMEMORY_API_KEY" \
|
||||
-H "Content-Type: application/json" \
|
||||
-d '{
|
||||
"q": "artificial intelligence research",
|
||||
"threshold": 0.7,
|
||||
"limit": 10
|
||||
}'
|
||||
```
|
||||
</Tab>
|
||||
</Tabs>
|
||||
|
||||
## Reranking
|
||||
|
||||
Improve result quality with secondary ranking:
|
||||
|
||||
<Tabs>
|
||||
<Tab title="TypeScript">
|
||||
```typescript
|
||||
const results = await client.search.memories({
|
||||
q: "quantum computing breakthrough",
|
||||
rerank: true, // Better relevance, slight latency increase
|
||||
limit: 5
|
||||
});
|
||||
```
|
||||
</Tab>
|
||||
<Tab title="Python">
|
||||
```python
|
||||
results = client.search.memories(
|
||||
q="quantum computing breakthrough",
|
||||
rerank=True, # Better relevance, slight latency increase
|
||||
limit=5
|
||||
)
|
||||
```
|
||||
</Tab>
|
||||
<Tab title="cURL">
|
||||
```bash
|
||||
curl -X POST "https://api.supermemory.ai/v4/search" \
|
||||
-H "Authorization: Bearer $SUPERMEMORY_API_KEY" \
|
||||
-H "Content-Type: application/json" \
|
||||
-d '{
|
||||
"q": "quantum computing breakthrough",
|
||||
"rerank": true,
|
||||
"limit": 5
|
||||
}'
|
||||
```
|
||||
</Tab>
|
||||
</Tabs>
|
||||
|
||||
## Query Rewriting
|
||||
|
||||
Improve search accuracy with automatic query expansion:
|
||||
|
||||
<Tabs>
|
||||
<Tab title="TypeScript">
|
||||
```typescript
|
||||
const results = await client.search.memories({
|
||||
q: "How do neural networks learn?",
|
||||
rewriteQuery: true, // +400ms latency but better results
|
||||
limit: 5
|
||||
});
|
||||
```
|
||||
</Tab>
|
||||
<Tab title="Python">
|
||||
```python
|
||||
results = client.search.memories(
|
||||
q="How do neural networks learn?",
|
||||
rewrite_query=True, # +400ms latency but better results
|
||||
limit=5
|
||||
)
|
||||
```
|
||||
</Tab>
|
||||
<Tab title="cURL">
|
||||
```bash
|
||||
curl -X POST "https://api.supermemory.ai/v4/search" \
|
||||
-H "Authorization: Bearer $SUPERMEMORY_API_KEY" \
|
||||
-H "Content-Type: application/json" \
|
||||
-d '{
|
||||
"q": "How do neural networks learn?",
|
||||
"rewriteQuery": true,
|
||||
"limit": 5
|
||||
}'
|
||||
```
|
||||
</Tab>
|
||||
</Tabs>
|
||||
|
||||
## Include Related Content
|
||||
|
||||
Include documents, related memories, and summaries:
|
||||
|
||||
<Tabs>
|
||||
<Tab title="TypeScript">
|
||||
```typescript
|
||||
const results = await client.search.memories({
|
||||
q: "machine learning trends",
|
||||
include: {
|
||||
documents: true, // Include source documents
|
||||
relatedMemories: true, // Include related memory entries
|
||||
summaries: true // Include memory summaries
|
||||
},
|
||||
limit: 5
|
||||
});
|
||||
```
|
||||
</Tab>
|
||||
<Tab title="Python">
|
||||
```python
|
||||
results = client.search.memories(
|
||||
q="machine learning trends",
|
||||
include={
|
||||
"documents": True, # Include source documents
|
||||
"relatedMemories": True, # Include related memory entries
|
||||
"summaries": True # Include memory summaries
|
||||
},
|
||||
limit=5
|
||||
)
|
||||
```
|
||||
</Tab>
|
||||
<Tab title="cURL">
|
||||
```bash
|
||||
curl -X POST "https://api.supermemory.ai/v4/search" \
|
||||
-H "Authorization: Bearer $SUPERMEMORY_API_KEY" \
|
||||
-H "Content-Type: application/json" \
|
||||
-d '{
|
||||
"q": "machine learning trends",
|
||||
"include": {
|
||||
"documents": true,
|
||||
"relatedMemories": true,
|
||||
"summaries": true
|
||||
},
|
||||
"limit": 5
|
||||
}'
|
||||
```
|
||||
</Tab>
|
||||
</Tabs>
|
||||
|
||||
## Metadata Filtering
|
||||
|
||||
Simple metadata filtering for Memories search:
|
||||
|
||||
<Tabs>
|
||||
<Tab title="TypeScript">
|
||||
```typescript
|
||||
const results = await client.search.memories({
|
||||
q: "research findings",
|
||||
filters: {
|
||||
AND: [
|
||||
{ key: "category", value: "science", negate: false },
|
||||
{ key: "status", value: "published", negate: false }
|
||||
]
|
||||
},
|
||||
limit: 10
|
||||
});
|
||||
```
|
||||
</Tab>
|
||||
<Tab title="Python">
|
||||
```python
|
||||
results = client.search.memories(
|
||||
q="research findings",
|
||||
filters={
|
||||
"AND": [
|
||||
{"key": "category", "value": "science", "negate": False},
|
||||
{"key": "status", "value": "published", "negate": False}
|
||||
]
|
||||
},
|
||||
limit=10
|
||||
)
|
||||
```
|
||||
</Tab>
|
||||
<Tab title="cURL">
|
||||
```bash
|
||||
curl -X POST "https://api.supermemory.ai/v4/search" \
|
||||
-H "Authorization: Bearer $SUPERMEMORY_API_KEY" \
|
||||
-H "Content-Type: application/json" \
|
||||
-d '{
|
||||
"q": "research findings",
|
||||
"filters": {
|
||||
"AND": [
|
||||
{"key": "category", "value": "science", "negate": false},
|
||||
{"key": "status", "value": "published", "negate": false}
|
||||
]
|
||||
},
|
||||
"limit": 10
|
||||
}'
|
||||
```
|
||||
</Tab>
|
||||
</Tabs>
|
||||
|
||||
## Chatbot Example
|
||||
|
||||
Optimal configuration for conversational AI:
|
||||
|
||||
<Tabs>
|
||||
<Tab title="TypeScript">
|
||||
```typescript
|
||||
// Optimized for chatbot responses
|
||||
const results = await client.search.memories({
|
||||
q: userMessage,
|
||||
containerTag: userId,
|
||||
threshold: 0.6, // Balanced relevance
|
||||
rerank: false, // Skip for speed
|
||||
rewriteQuery: false, // Skip for speed
|
||||
limit: 3 // Few, relevant results
|
||||
});
|
||||
|
||||
// Quick response for chat
|
||||
const context = results.results
|
||||
.map(r => r.memory)
|
||||
.join('\n\n');
|
||||
```
|
||||
</Tab>
|
||||
<Tab title="Python">
|
||||
```python
|
||||
# Optimized for chatbot responses
|
||||
results = client.search.memories(
|
||||
q=user_message,
|
||||
container_tag=user_id,
|
||||
threshold=0.6, # Balanced relevance
|
||||
rerank=False, # Skip for speed
|
||||
rewrite_query=False, # Skip for speed
|
||||
limit=3 # Few, relevant results
|
||||
)
|
||||
|
||||
# Quick response for chat
|
||||
context = '\n\n'.join([r.memory for r in results.results])
|
||||
```
|
||||
</Tab>
|
||||
<Tab title="cURL">
|
||||
```bash
|
||||
# Optimized for chatbot responses
|
||||
curl -X POST "https://api.supermemory.ai/v4/search" \
|
||||
-H "Authorization: Bearer $SUPERMEMORY_API_KEY" \
|
||||
-H "Content-Type: application/json" \
|
||||
-d '{
|
||||
"q": "user question here",
|
||||
"containerTag": "user_123",
|
||||
"threshold": 0.6,
|
||||
"rerank": false,
|
||||
"rewriteQuery": false,
|
||||
"limit": 3
|
||||
}'
|
||||
```
|
||||
</Tab>
|
||||
</Tabs>
|
||||
|
||||
## Complete Memories Search Example
|
||||
|
||||
Combining features for comprehensive results:
|
||||
|
||||
<Tabs>
|
||||
<Tab title="TypeScript">
|
||||
```typescript
|
||||
const results = await client.search.memories({
|
||||
q: "machine learning model performance",
|
||||
containerTag: "research_team",
|
||||
filters: {
|
||||
AND: [
|
||||
{ key: "topic", value: "ai", negate: false }
|
||||
]
|
||||
},
|
||||
threshold: 0.7,
|
||||
rerank: true,
|
||||
rewriteQuery: false, // Skip for speed
|
||||
include: {
|
||||
documents: true,
|
||||
relatedMemories: false,
|
||||
summaries: true
|
||||
},
|
||||
limit: 5
|
||||
});
|
||||
```
|
||||
</Tab>
|
||||
<Tab title="Python">
|
||||
```python
|
||||
results = client.search.memories(
|
||||
q="machine learning model performance",
|
||||
container_tag="research_team",
|
||||
filters={
|
||||
"AND": [
|
||||
{"key": "topic", "value": "ai", "negate": False}
|
||||
]
|
||||
},
|
||||
threshold=0.7,
|
||||
rerank=True,
|
||||
rewrite_query=False, # Skip for speed
|
||||
include={
|
||||
"documents": True,
|
||||
"relatedMemories": False,
|
||||
"summaries": True
|
||||
},
|
||||
limit=5
|
||||
)
|
||||
```
|
||||
</Tab>
|
||||
<Tab title="cURL">
|
||||
```bash
|
||||
curl -X POST "https://api.supermemory.ai/v4/search" \
|
||||
-H "Authorization: Bearer $SUPERMEMORY_API_KEY" \
|
||||
-H "Content-Type: application/json" \
|
||||
-d '{
|
||||
"q": "machine learning model performance",
|
||||
"containerTag": "research_team",
|
||||
"filters": {
|
||||
"AND": [
|
||||
{"key": "topic", "value": "ai", "negate": false}
|
||||
]
|
||||
},
|
||||
"threshold": 0.7,
|
||||
"rerank": true,
|
||||
"rewriteQuery": false,
|
||||
"include": {
|
||||
"documents": true,
|
||||
"relatedMemories": false,
|
||||
"summaries": true
|
||||
},
|
||||
"limit": 5
|
||||
}'
|
||||
```
|
||||
</Tab>
|
||||
</Tabs>
|
||||
|
||||
## Hybrid Search Mode
|
||||
|
||||
Hybrid search mode allows you to search both memories and document chunks in a single request. When `searchMode="hybrid"`, results contain objects with either a `memory` key (for memory results) or a `chunk` key (for chunk results).
|
||||
|
||||
### Basic Hybrid Search
|
||||
|
||||
<Tabs>
|
||||
<Tab title="TypeScript">
|
||||
```typescript
|
||||
const results = await client.search.memories({
|
||||
q: "machine learning best practices",
|
||||
searchMode: "hybrid", // Search memories + chunks
|
||||
limit: 10
|
||||
});
|
||||
|
||||
// Handle mixed results
|
||||
results.results.forEach(result => {
|
||||
if ('memory' in result) {
|
||||
console.log('Memory:', result.memory);
|
||||
} else if ('chunk' in result) {
|
||||
console.log('Chunk:', result.chunk);
|
||||
console.log('From document:', result.documents?.[0]?.title);
|
||||
}
|
||||
});
|
||||
```
|
||||
</Tab>
|
||||
<Tab title="Python">
|
||||
```python
|
||||
results = client.search.memories(
|
||||
q="machine learning best practices",
|
||||
search_mode="hybrid", # Search memories + chunks
|
||||
limit=10
|
||||
)
|
||||
|
||||
# Handle mixed results
|
||||
for result in results.results:
|
||||
if 'memory' in result:
|
||||
print('Memory:', result['memory'])
|
||||
elif 'chunk' in result:
|
||||
print('Chunk:', result['chunk'])
|
||||
print('From document:', result.get('documents', [{}])[0].get('title'))
|
||||
```
|
||||
</Tab>
|
||||
<Tab title="cURL">
|
||||
```bash
|
||||
curl -X POST "https://api.supermemory.ai/v4/search" \
|
||||
-H "Authorization: Bearer $SUPERMEMORY_API_KEY" \
|
||||
-H "Content-Type: application/json" \
|
||||
-d '{
|
||||
"q": "machine learning best practices",
|
||||
"searchMode": "hybrid",
|
||||
"limit": 10
|
||||
}'
|
||||
```
|
||||
</Tab>
|
||||
</Tabs>
|
||||
|
||||
### When to Use Hybrid Mode
|
||||
|
||||
Use hybrid mode when:
|
||||
- You want comprehensive search across both memories and documents
|
||||
- Memories might not exist for certain queries but document content is available
|
||||
- You need flexibility to get either memory or document chunk results
|
||||
- You want a single search endpoint that covers all content types
|
||||
|
||||
Use memories-only mode (`searchMode="memories"`) when:
|
||||
- You only need user memories and preferences
|
||||
- You want faster, more focused results
|
||||
- You're building a personalized chatbot that relies on user context
|
||||
|
||||
### Handling Mixed Results
|
||||
|
||||
When using hybrid mode, you'll receive mixed results. Here's how to process them:
|
||||
|
||||
<Tabs>
|
||||
<Tab title="TypeScript">
|
||||
```typescript
|
||||
const results = await client.search.memories({
|
||||
q: "quantum computing applications",
|
||||
searchMode: "hybrid",
|
||||
limit: 10
|
||||
});
|
||||
|
||||
// Separate memory and chunk results
|
||||
const memoryResults = results.results.filter(r => 'memory' in r);
|
||||
const chunkResults = results.results.filter(r => 'chunk' in r);
|
||||
|
||||
console.log(`Found ${memoryResults.length} memories and ${chunkResults.length} chunks`);
|
||||
|
||||
// Process memories
|
||||
memoryResults.forEach(mem => {
|
||||
console.log('Memory:', mem.memory);
|
||||
console.log('Similarity:', mem.similarity);
|
||||
});
|
||||
|
||||
// Process chunks
|
||||
chunkResults.forEach(chunk => {
|
||||
console.log('Chunk:', chunk.chunk);
|
||||
console.log('Document:', chunk.documents?.[0]?.title);
|
||||
console.log('Similarity:', chunk.similarity);
|
||||
});
|
||||
```
|
||||
</Tab>
|
||||
<Tab title="Python">
|
||||
```python
|
||||
results = client.search.memories(
|
||||
q="quantum computing applications",
|
||||
search_mode="hybrid",
|
||||
limit=10
|
||||
)
|
||||
|
||||
# Separate memory and chunk results
|
||||
memory_results = [r for r in results.results if 'memory' in r]
|
||||
chunk_results = [r for r in results.results if 'chunk' in r]
|
||||
|
||||
print(f"Found {len(memory_results)} memories and {len(chunk_results)} chunks")
|
||||
|
||||
# Process memories
|
||||
for mem in memory_results:
|
||||
print('Memory:', mem['memory'])
|
||||
print('Similarity:', mem['similarity'])
|
||||
|
||||
# Process chunks
|
||||
for chunk in chunk_results:
|
||||
print('Chunk:', chunk['chunk'])
|
||||
print('Document:', chunk.get('documents', [{}])[0].get('title'))
|
||||
print('Similarity:', chunk['similarity'])
|
||||
```
|
||||
</Tab>
|
||||
</Tabs>
|
||||
|
||||
### Hybrid Search with All Features
|
||||
|
||||
Combining hybrid mode with other features:
|
||||
|
||||
<Tabs>
|
||||
<Tab title="TypeScript">
|
||||
```typescript
|
||||
const results = await client.search.memories({
|
||||
q: "research findings on AI",
|
||||
searchMode: "hybrid",
|
||||
containerTag: "research_team",
|
||||
threshold: 0.7,
|
||||
rerank: true,
|
||||
include: {
|
||||
documents: true,
|
||||
relatedMemories: true,
|
||||
summaries: true
|
||||
},
|
||||
limit: 10
|
||||
});
|
||||
|
||||
// Results are automatically sorted by similarity
|
||||
// Memory results have 'memory' field, chunk results have 'chunk' field
|
||||
results.results.forEach(result => {
|
||||
if ('memory' in result) {
|
||||
// Memory result
|
||||
console.log('Memory:', result.memory);
|
||||
console.log('Context:', result.context);
|
||||
} else {
|
||||
// Chunk result
|
||||
console.log('Chunk:', result.chunk);
|
||||
console.log('Document:', result.documents?.[0]);
|
||||
}
|
||||
});
|
||||
```
|
||||
</Tab>
|
||||
<Tab title="Python">
|
||||
```python
|
||||
results = client.search.memories(
|
||||
q="research findings on AI",
|
||||
search_mode="hybrid",
|
||||
container_tag="research_team",
|
||||
threshold=0.7,
|
||||
rerank=True,
|
||||
include={
|
||||
"documents": True,
|
||||
"relatedMemories": True,
|
||||
"summaries": True
|
||||
},
|
||||
limit=10
|
||||
)
|
||||
|
||||
# Results are automatically sorted by similarity
|
||||
# Memory results have 'memory' field, chunk results have 'chunk' field
|
||||
for result in results.results:
|
||||
if 'memory' in result:
|
||||
# Memory result
|
||||
print('Memory:', result['memory'])
|
||||
print('Context:', result.get('context'))
|
||||
else:
|
||||
# Chunk result
|
||||
print('Chunk:', result['chunk'])
|
||||
print('Document:', result.get('documents', [{}])[0])
|
||||
```
|
||||
</Tab>
|
||||
<Tab title="cURL">
|
||||
```bash
|
||||
curl -X POST "https://api.supermemory.ai/v4/search" \
|
||||
-H "Authorization: Bearer $SUPERMEMORY_API_KEY" \
|
||||
-H "Content-Type: application/json" \
|
||||
-d '{
|
||||
"q": "research findings on AI",
|
||||
"searchMode": "hybrid",
|
||||
"containerTag": "research_team",
|
||||
"threshold": 0.7,
|
||||
"rerank": true,
|
||||
"include": {
|
||||
"documents": true,
|
||||
"relatedMemories": true,
|
||||
"summaries": true
|
||||
},
|
||||
"limit": 10
|
||||
}'
|
||||
```
|
||||
</Tab>
|
||||
</Tabs>
|
||||
|
||||
<Note>
|
||||
**Important**: In hybrid mode, results are automatically merged and sorted by similarity score. Memory results and chunk results are deduplicated - if a chunk is already associated with a memory result, it won't appear as a separate chunk result.
|
||||
</Note>
|
||||
|
||||
## Common Use Cases
|
||||
|
||||
- **Chatbots**: Basic search with container tag and low threshold
|
||||
- **Q&A Systems**: Add reranking for better relevance
|
||||
- **Knowledge Retrieval**: Include documents and summaries
|
||||
- **Real-time Search**: Skip rewriting and reranking for maximum speed
|
||||
- **Hybrid Search**: Use `searchMode="hybrid"` when you need comprehensive search across both memories and documents
|
||||
|
|
@ -1,493 +0,0 @@
|
|||
---
|
||||
title: "Search with Filters & Scoring"
|
||||
description: "Semantic and hybrid search with metadata filters, scoring, and precise result control"
|
||||
sidebarTitle : "Overview"
|
||||
---
|
||||
|
||||
## Prerequisites
|
||||
|
||||
Before searching memories, you need to set up the Supermemory client:
|
||||
|
||||
- **Install the SDK** for your language
|
||||
- **Get your API key** from [Supermemory Console](https://console.supermemory.ai)
|
||||
- **Initialize the client** with your API key
|
||||
|
||||
<CodeGroup>
|
||||
|
||||
```bash npm
|
||||
npm install supermemory
|
||||
```
|
||||
|
||||
```bash pip
|
||||
pip install supermemory
|
||||
```
|
||||
|
||||
</CodeGroup>
|
||||
|
||||
<CodeGroup>
|
||||
|
||||
```typescript TypeScript
|
||||
import Supermemory from 'supermemory';
|
||||
|
||||
const client = new Supermemory({
|
||||
apiKey: process.env.SUPERMEMORY_API_KEY!
|
||||
});
|
||||
```
|
||||
|
||||
```python Python
|
||||
from supermemory import Supermemory
|
||||
import os
|
||||
|
||||
client = Supermemory(
|
||||
api_key=os.environ.get("SUPERMEMORY_API_KEY")
|
||||
)
|
||||
```
|
||||
|
||||
</CodeGroup>
|
||||
|
||||
## Search Endpoints Overview
|
||||
|
||||
<CardGroup cols={2}>
|
||||
<Card title="Documents Search - Fast, Advanced RAG" icon="settings" href="/search/examples/document-search">
|
||||
**POST /v3/search**
|
||||
|
||||
Full-featured search with extensive control over ranking, filtering, thresholds, and result structure. Searches through and returns relevant documents. More flexibility.
|
||||
</Card>
|
||||
|
||||
<Card title="Memories Search" icon="zap" href="/search/examples/memory-search">
|
||||
**POST /v4/search**
|
||||
|
||||
Minimal-latency search optimized for chatbots and conversational AI. Searches through and returns memories. Simple parameters, fast responses, easy to use.
|
||||
</Card>
|
||||
</CardGroup>
|
||||
|
||||
## Documents vs Memories Search: What's the Difference?
|
||||
|
||||
The key difference between `/v3/search` and `/v4/search` is **documents vs memories**. `/v3/search` searches through the documents and returns matching chunks, whereas `/v4/search` searches through user's memories, preferences and history.
|
||||
|
||||
- **Documents:** Refer to the data you ingest like text, pdfs, videos, images, etc. They are sources of ground truth.
|
||||
- **Memories:** They are automatically extracted from your documents by Supermemory. Smaller information chunks inferred from documents and related to each other.
|
||||
|
||||
Refer to the [ingestion guide](/memory-api/ingesting) to learn more about the difference between documents and memories.
|
||||
|
||||
### Documents Search (`/v3/search`)
|
||||
**High quality documents search** - extensive parameters for fine-tuning search behavior:
|
||||
|
||||
- **Use cases**: Use this endpoint for use cases where "literal" document search is required.
|
||||
- Looking through legal/finance documents
|
||||
- Searching through items in google drive
|
||||
- Chat with documentation
|
||||
- With this endpoint, you get **Full Control** over
|
||||
- Thresholds,
|
||||
- Filtering
|
||||
- Reranking
|
||||
- Query rewriting
|
||||
|
||||
<Tabs>
|
||||
<Tab title="TypeScript">
|
||||
```typescript
|
||||
// Documents search
|
||||
const results = await client.search.documents({
|
||||
q: "machine learning accuracy",
|
||||
limit: 10,
|
||||
documentThreshold: 0.7,
|
||||
chunkThreshold: 0.8,
|
||||
rerank: true,
|
||||
rewriteQuery: true,
|
||||
includeFullDocs: true,
|
||||
includeSummary: true,
|
||||
onlyMatchingChunks: false,
|
||||
containerTags: ["research"],
|
||||
filters: {
|
||||
AND: [{ key: "category", value: "ai", negate: false }]
|
||||
}
|
||||
});
|
||||
```
|
||||
</Tab>
|
||||
<Tab title="Python">
|
||||
```python
|
||||
# Documents search
|
||||
results = client.search.documents(
|
||||
q="machine learning accuracy",
|
||||
limit=10,
|
||||
document_threshold=0.7,
|
||||
chunk_threshold=0.8,
|
||||
rerank=True,
|
||||
rewrite_query=True,
|
||||
include_full_docs=True,
|
||||
include_summary=True,
|
||||
only_matching_chunks=False,
|
||||
container_tags=["research"],
|
||||
filters={
|
||||
"AND": [{"key": "category", "value": "ai", "negate": False}]
|
||||
}
|
||||
)
|
||||
```
|
||||
</Tab>
|
||||
<Tab title="cURL">
|
||||
```bash
|
||||
curl -X POST "https://api.supermemory.ai/v3/search" \
|
||||
-H "Authorization: Bearer $SUPERMEMORY_API_KEY" \
|
||||
-H "Content-Type: application/json" \
|
||||
-d '{
|
||||
"q": "machine learning accuracy",
|
||||
"limit": 10,
|
||||
"documentThreshold": 0.7,
|
||||
"chunkThreshold": 0.8,
|
||||
"rerank": true,
|
||||
"rewriteQuery": true,
|
||||
"includeFullDocs": true,
|
||||
"includeSummary": true,
|
||||
"onlyMatchingChunks": false,
|
||||
"containerTags": ["research"],
|
||||
"filters": {
|
||||
"AND": [{"key": "category", "value": "ai", "negate": false}]
|
||||
}
|
||||
}'
|
||||
```
|
||||
</Tab>
|
||||
</Tabs>
|
||||
|
||||
```json Sample Response
|
||||
|
||||
{
|
||||
"results": [
|
||||
{
|
||||
"documentId": "doc_abc123",
|
||||
"title": "Machine Learning Fundamentals",
|
||||
"type": "pdf",
|
||||
"score": 0.89,
|
||||
"chunks": [
|
||||
{
|
||||
"content": "Machine learning is a subset of artificial intelligence...",
|
||||
"score": 0.95,
|
||||
"isRelevant": true
|
||||
}
|
||||
],
|
||||
"metadata": {
|
||||
"category": "education",
|
||||
"author": "Dr. Smith",
|
||||
"difficulty": "beginner"
|
||||
},
|
||||
"createdAt": "2024-01-15T10:30:00Z",
|
||||
"updatedAt": "2024-01-20T14:45:00Z"
|
||||
}
|
||||
],
|
||||
"timing": 187,
|
||||
"total": 1
|
||||
}
|
||||
```
|
||||
|
||||
The `/v3/search` endpoint returns the most relevant documents and chunks from those documents. Head over to the [response schema](/search/response-schema) page to understand more about the response structure.
|
||||
|
||||
### Memories Search (`/v4/search`)
|
||||
**Search through user memories**:
|
||||
|
||||
- **Use cases**: Use this endpoint for use cases where understanding user context / preferences / memories is more important than literal document search.
|
||||
- Personalized chatbots (AI Companions)
|
||||
- Auto selecting based on what the user wants
|
||||
- Setting the tone of the conversation
|
||||
|
||||
Companies like Composio [Rube.app](https://rube.app) use memories search for letting the MCP automate better based on the user prompts before.
|
||||
|
||||
<Info>
|
||||
This endpoint works best for conversational AI use cases like chatbots.
|
||||
</Info>
|
||||
|
||||
**Hybrid Search Mode:**
|
||||
|
||||
The `/v4/search` endpoint supports a `searchMode` parameter with two options:
|
||||
|
||||
- **`"memories"`** (default): Searches only memory entries. Returns results with a `memory` key containing the memory content.
|
||||
- **`"hybrid"`**: Searches memories first, then falls back to document chunks if needed. Returns mixed results where each result object has either a `memory` key (for memory results) or a `chunk` key (for chunk results from documents).
|
||||
|
||||
<Note>
|
||||
In hybrid mode, results are automatically merged by similarity score and deduplicated. Check for the presence of `memory` or `chunk` keys to distinguish result types.
|
||||
</Note>
|
||||
|
||||
<Tabs>
|
||||
<Tab title="TypeScript">
|
||||
```typescript
|
||||
// Memories search (default mode)
|
||||
const results = await client.search.memories({
|
||||
q: "machine learning accuracy",
|
||||
limit: 5,
|
||||
containerTag: "research",
|
||||
threshold: 0.7,
|
||||
rerank: true,
|
||||
searchMode: "memories" // Default: only search memories
|
||||
});
|
||||
|
||||
// Hybrid search (memories + chunks)
|
||||
const hybridResults = await client.search.memories({
|
||||
q: "machine learning accuracy",
|
||||
limit: 5,
|
||||
containerTag: "research",
|
||||
threshold: 0.7,
|
||||
searchMode: "hybrid" // Search memories + fallback to chunks
|
||||
});
|
||||
```
|
||||
</Tab>
|
||||
<Tab title="Python">
|
||||
```python
|
||||
# Memories search (default mode)
|
||||
results = client.search.memories(
|
||||
q="machine learning accuracy",
|
||||
limit=5,
|
||||
container_tag="research",
|
||||
threshold=0.7,
|
||||
rerank=True,
|
||||
search_mode="memories" # Default: only search memories
|
||||
)
|
||||
|
||||
# Hybrid search (memories + chunks)
|
||||
hybrid_results = client.search.memories(
|
||||
q="machine learning accuracy",
|
||||
limit=5,
|
||||
container_tag="research",
|
||||
threshold=0.7,
|
||||
search_mode="hybrid" # Search memories + fallback to chunks
|
||||
)
|
||||
```
|
||||
</Tab>
|
||||
<Tab title="cURL">
|
||||
```bash
|
||||
# Memories search (default mode)
|
||||
curl -X POST "https://api.supermemory.ai/v4/search" \
|
||||
-H "Authorization: Bearer $SUPERMEMORY_API_KEY" \
|
||||
-H "Content-Type: application/json" \
|
||||
-d '{
|
||||
"q": "machine learning accuracy",
|
||||
"limit": 5,
|
||||
"containerTag": "research",
|
||||
"threshold": 0.7,
|
||||
"rerank": true,
|
||||
}'
|
||||
|
||||
# Hybrid search (memories + chunks)
|
||||
curl -X POST "https://api.supermemory.ai/v4/search" \
|
||||
-H "Authorization: Bearer $SUPERMEMORY_API_KEY" \
|
||||
-H "Content-Type: application/json" \
|
||||
-d '{
|
||||
"q": "machine learning accuracy",
|
||||
"limit": 5,
|
||||
"containerTag": "research",
|
||||
"threshold": 0.7,
|
||||
"rerank": true,
|
||||
"searchMode": "hybrid"
|
||||
}'
|
||||
```
|
||||
</Tab>
|
||||
</Tabs>
|
||||
|
||||
|
||||
```json Sample Response
|
||||
{
|
||||
"results": [
|
||||
{
|
||||
"id": "mem_xyz789",
|
||||
"memory": "Complete memory content about quantum computing applications...",
|
||||
"similarity": 0.87,
|
||||
"metadata": {
|
||||
"category": "research",
|
||||
"topic": "quantum-computing"
|
||||
},
|
||||
"updatedAt": "2024-01-18T09:15:00Z",
|
||||
"version": 3,
|
||||
"context": {
|
||||
"parents": [
|
||||
{
|
||||
"memory": "Earlier discussion about quantum theory basics...",
|
||||
"relation": "extends",
|
||||
"version": 2,
|
||||
"updatedAt": "2024-01-17T16:30:00Z"
|
||||
}
|
||||
],
|
||||
"children": [
|
||||
{
|
||||
"memory": "Follow-up questions about quantum algorithms...",
|
||||
"relation": "derives",
|
||||
"version": 4,
|
||||
"updatedAt": "2024-01-19T11:20:00Z"
|
||||
}
|
||||
]
|
||||
},
|
||||
"documents": [
|
||||
{
|
||||
"id": "doc_quantum_paper",
|
||||
"title": "Quantum Computing Applications",
|
||||
"type": "pdf",
|
||||
"createdAt": "2024-01-10T08:00:00Z"
|
||||
}
|
||||
]
|
||||
}
|
||||
],
|
||||
"timing": 156,
|
||||
"total": 1
|
||||
}
|
||||
|
||||
```
|
||||
|
||||
The `/v4/search` endpoint searches through and returns memories. With `searchMode="hybrid"`, it can also return document chunks when memories aren't found, providing comprehensive search coverage.
|
||||
|
||||
## Direct Document Retrieval
|
||||
|
||||
If you don't need semantic search and just want to retrieve a specific document you've uploaded by its ID, use the GET document endpoint:
|
||||
|
||||
`GET /v3/documents/{id}`
|
||||
|
||||
This is useful when:
|
||||
- You know the exact document ID
|
||||
- You want to retrieve the full document content and metadata
|
||||
- You need to check processing status or document details
|
||||
|
||||
<CodeGroup>
|
||||
|
||||
```typescript TypeScript
|
||||
// Get a specific document by ID
|
||||
const document = await client.documents.get("doc_abc123");
|
||||
|
||||
console.log(document.content); // Full document content
|
||||
console.log(document.status); // Processing status
|
||||
console.log(document.metadata); // Document metadata
|
||||
console.log(document.summary); // AI-generated summary
|
||||
```
|
||||
|
||||
```python Python
|
||||
# Get a specific document by ID
|
||||
document = client.documents.get("doc_abc123")
|
||||
|
||||
print(document.content) # Full document content
|
||||
print(document.status) # Processing status
|
||||
```
|
||||
|
||||
```bash cURL
|
||||
curl -X GET "https://api.supermemory.ai/v3/documents/{YOUR-DOCUMENT-ID}" \
|
||||
-H "Authorization: Bearer $SUPERMEMORY_API_KEY"
|
||||
```
|
||||
|
||||
</CodeGroup>
|
||||
|
||||
<Note>
|
||||
This endpoint returns the complete document with all fields including content, metadata, containerTags, summary, and processing status. For more details, see the API Reference tab.
|
||||
</Note>
|
||||
|
||||
## Search Flow Architecture
|
||||
|
||||
### Document Search (`/v3/search`) Flow
|
||||
|
||||
```mermaid
|
||||
graph TD
|
||||
A[Query Input] --> B{Rewrite Query?}
|
||||
B -->|Yes| C[Query Rewriting +400ms]
|
||||
B -->|No| D[Generate Embeddings]
|
||||
C --> E[Generate Rewritten Embeddings]
|
||||
D --> F[Search Execution]
|
||||
E --> F
|
||||
F --> G[Apply Filtering<br/>metadata, categories, containerTags]
|
||||
G --> H{Rerank?}
|
||||
H -->|Yes| I[Apply Reranking]
|
||||
H -->|No| J[Build Results with Chunks]
|
||||
I --> J
|
||||
J --> K[Return Documents + Chunks + Scores]
|
||||
```
|
||||
|
||||
### Memory Search (`/v4/search`) Flow
|
||||
|
||||
```mermaid
|
||||
graph TD
|
||||
A[Query Input] --> B[Query Rewriting + Embedding]
|
||||
B --> C[Parallel Search Execution]
|
||||
C --> D[Apply Filtering]
|
||||
D --> E[Merge Results]
|
||||
E --> F[Deduplication]
|
||||
F --> G{Rerank?}
|
||||
G -->|Yes| H[Apply Reranking]
|
||||
G -->|No| I[Return Memories + Similarity]
|
||||
H --> I
|
||||
```
|
||||
|
||||
## Key Concepts You Need to Understand
|
||||
|
||||
### 1. Thresholds (Sensitivity Control)
|
||||
|
||||
Thresholds control result quality vs quantity:
|
||||
|
||||
- **0.0** = Least sensitive (more results, lower quality)
|
||||
- **1.0** = Most sensitive (fewer results, higher quality)
|
||||
|
||||
```typescript
|
||||
// Different threshold strategies
|
||||
const broadSearch = await client.search.documents({
|
||||
q: "machine learning",
|
||||
chunkThreshold: 0.2, // Return more chunks
|
||||
documentThreshold: 0.1 // From more documents
|
||||
});
|
||||
|
||||
const preciseSearch = await client.search.documents({
|
||||
q: "machine learning",
|
||||
chunkThreshold: 0.8, // Only highly relevant chunks
|
||||
documentThreshold: 0.7 // From closely matching documents
|
||||
});
|
||||
```
|
||||
|
||||
### 2. Chunk Context vs Exact Matching
|
||||
|
||||
By default, Supermemory returns chunks **with context** (surrounding text):
|
||||
|
||||
```typescript
|
||||
// Default: includes surrounding chunks for context
|
||||
const contextualResults = await client.search.documents({
|
||||
q: "neural networks",
|
||||
onlyMatchingChunks: false // Default
|
||||
});
|
||||
|
||||
// Precise: only the exact matching text
|
||||
const exactResults = await client.search.documents({
|
||||
q: "neural networks",
|
||||
onlyMatchingChunks: true
|
||||
});
|
||||
```
|
||||
|
||||
### 3. Query Rewriting & Reranking
|
||||
|
||||
**Query Rewriting** (+400ms latency):
|
||||
- Expands your query to find more relevant results
|
||||
- "ML" becomes "machine learning artificial intelligence"
|
||||
- Useful for abbreviations and domain-specific terms
|
||||
|
||||
**Reranking**:
|
||||
- Re-scores results using a different algorithm
|
||||
- More accurate but slower
|
||||
- Recommended for critical searches
|
||||
|
||||
### 4. Container Tags vs Metadata Filters
|
||||
|
||||
Two different filtering mechanisms:
|
||||
|
||||
When to use container tags:
|
||||
- The user understanding graph is built on top of container tags. **The graph is formed on top of container tags.**
|
||||
- Container tags are used for organizational grouping and exact matching.
|
||||
- They are useful for categorizing content and ensuring precise results.
|
||||
When to use metadata filters:
|
||||
- When you need flexible conditions beyond exact matches.
|
||||
- Useful for filtering by attributes like date, author, or category.
|
||||
|
||||
```typescript
|
||||
// Container tags: Organizational grouping (exact array matching)
|
||||
const userContent = await client.search.documents({
|
||||
q: "python tutorial",
|
||||
containerTag "user_123" // Must match exactly
|
||||
});
|
||||
|
||||
// Metadata filters: SQL-based queries (flexible conditions)
|
||||
const filteredContent = await client.search.documents({
|
||||
q: "python tutorial",
|
||||
filters: JSON.stringify({
|
||||
AND: [
|
||||
{ key: "language", value: "python", negate: false },
|
||||
{ key: "difficulty", value: "beginner", negate: false }
|
||||
]
|
||||
})
|
||||
});
|
||||
```
|
||||
|
|
@ -1,264 +0,0 @@
|
|||
---
|
||||
title: "Search Parameters"
|
||||
description: "Complete reference for all search parameters and their effects"
|
||||
---
|
||||
|
||||
|
||||
Complete parameter reference for all three search endpoints: document search, memory search, and execute search.
|
||||
|
||||
## Common Parameters
|
||||
|
||||
These parameters work across all search endpoints:
|
||||
|
||||
<ParamField query="q" type="string" required>
|
||||
**Search query string**
|
||||
|
||||
The text you want to search for. Can be natural language, keywords, or questions.
|
||||
|
||||
```typescript
|
||||
q: "machine learning neural networks"
|
||||
q: "What are the applications of quantum computing?"
|
||||
q: "python tutorial beginner"
|
||||
```
|
||||
</ParamField>
|
||||
|
||||
<ParamField query="limit" type="number" default="10">
|
||||
**Maximum number of results to return**
|
||||
|
||||
Controls how many results you get back. Higher limits increase response time and size.
|
||||
|
||||
```typescript
|
||||
limit: 5 // Fast, focused results
|
||||
limit: 20 // Comprehensive results
|
||||
limit: 100 // Maximum recommended
|
||||
```
|
||||
</ParamField>
|
||||
|
||||
<ParamField query="containerTags" type="Array<string>">
|
||||
**Filter by container tags**
|
||||
|
||||
Organizational tags for filtering results. Uses **exact array matching** - must match all tags in the same order.
|
||||
|
||||
```typescript
|
||||
containerTags: ["user_123"] // Single tag
|
||||
containerTags: ["user_123", "project_ai"] // Multiple tags (exact match)
|
||||
```
|
||||
</ParamField>
|
||||
|
||||
<ParamField query="filters" type="string">
|
||||
**Metadata filtering with SQL-like structure**
|
||||
|
||||
JSON string containing AND/OR logic for filtering by metadata fields. Uses the same structure as memory listing filters.
|
||||
|
||||
```typescript
|
||||
filters: JSON.stringify({
|
||||
AND: [
|
||||
{ key: "category", value: "tutorial", negate: false },
|
||||
{ key: "difficulty", value: "beginner", negate: false }
|
||||
]
|
||||
})
|
||||
```
|
||||
|
||||
<Note>
|
||||
See [Metadata Filtering Guide](/concepts/filtering) for complete syntax and examples.
|
||||
</Note>
|
||||
</ParamField>
|
||||
|
||||
<ParamField query="rerank" type="boolean" default="false">
|
||||
**Re-score results for better relevance**
|
||||
|
||||
Applies a secondary ranking algorithm to improve result quality. Adds ~100-200ms latency but increases accuracy.
|
||||
|
||||
```typescript
|
||||
rerank: true // Better accuracy, slower
|
||||
rerank: false // Faster, standard accuracy
|
||||
```
|
||||
</ParamField>
|
||||
|
||||
<ParamField query="rewriteQuery" type="boolean" default="false">
|
||||
**Expand and improve the query**
|
||||
|
||||
Rewrites your query to find more relevant results. Particularly useful for abbreviations and domain-specific terms. **Adds ~400ms latency**.
|
||||
|
||||
```typescript
|
||||
// Query rewriting examples:
|
||||
"ML" → "machine learning artificial intelligence"
|
||||
"JS" → "JavaScript programming language"
|
||||
"API" → "application programming interface REST"
|
||||
```
|
||||
|
||||
<Warning>
|
||||
Query rewriting significantly increases latency. Only use when search quality is more important than speed.
|
||||
</Warning>
|
||||
</ParamField>
|
||||
|
||||
## Document Search Parameters (POST `/v3/search`)
|
||||
|
||||
These parameters are specific to `client.search.documents()`:
|
||||
|
||||
<ParamField query="chunkThreshold" type="number" range="0-1" default="0.5">
|
||||
**Sensitivity for chunk selection**
|
||||
|
||||
Controls which text chunks are included in results:
|
||||
- **0.0** = Least sensitive (more chunks, more results)
|
||||
- **1.0** = Most sensitive (fewer chunks, higher quality)
|
||||
|
||||
```typescript
|
||||
chunkThreshold: 0.2 // Broad search, many chunks
|
||||
chunkThreshold: 0.8 // Precise search, only relevant chunks
|
||||
```
|
||||
</ParamField>
|
||||
|
||||
<ParamField query="documentThreshold" type="number" range="0-1" default="0.5">
|
||||
**Sensitivity for document selection**
|
||||
|
||||
Controls which documents are considered for search:
|
||||
- **0.0** = Search more documents (comprehensive)
|
||||
- **1.0** = Search only highly relevant documents (focused)
|
||||
|
||||
```typescript
|
||||
documentThreshold: 0.1 // Cast wide net
|
||||
documentThreshold: 0.9 // Only very relevant documents
|
||||
```
|
||||
</ParamField>
|
||||
|
||||
<ParamField query="docId" type="string">
|
||||
**Search within a specific document**
|
||||
|
||||
Limit search to chunks within a single document. Useful for finding content in large documents.
|
||||
|
||||
```typescript
|
||||
docId: "doc_abc123" // Only search this document
|
||||
```
|
||||
</ParamField>
|
||||
|
||||
<ParamField query="onlyMatchingChunks" type="boolean" default="false">
|
||||
**Return only exact matching chunks**
|
||||
|
||||
By default, Supermemory includes surrounding chunks for context. Set to `true` to get only the exact matching text.
|
||||
|
||||
```typescript
|
||||
onlyMatchingChunks: false // Include context chunks (default)
|
||||
onlyMatchingChunks: true // Only matching chunks
|
||||
```
|
||||
|
||||
<Note>
|
||||
Context chunks help LLMs understand the full meaning. Only disable if you need precise text extraction.
|
||||
</Note>
|
||||
</ParamField>
|
||||
|
||||
<ParamField query="includeFullDocs" type="boolean" default="false">
|
||||
**Include complete document content**
|
||||
|
||||
Adds the full document text to each result. Useful for chatbots that need complete context.
|
||||
|
||||
```typescript
|
||||
includeFullDocs: true // Full document in response
|
||||
includeFullDocs: false // Only chunks and metadata
|
||||
```
|
||||
|
||||
<Warning>
|
||||
Including full documents can make responses very large. Use sparingly and with appropriate limits.
|
||||
</Warning>
|
||||
</ParamField>
|
||||
|
||||
<ParamField query="includeSummary" type="boolean" default="false">
|
||||
**Include document summaries**
|
||||
|
||||
Adds AI-generated document summaries to results. Good middle-ground between chunks and full documents.
|
||||
|
||||
```typescript
|
||||
includeSummary: true // Include document summaries
|
||||
includeSummary: false // No summaries
|
||||
```
|
||||
</ParamField>
|
||||
|
||||
<ParamField query="filters" type="string">
|
||||
**Filter by metadata using SQL queries**
|
||||
|
||||
```typescript
|
||||
|
||||
// Use this instead:
|
||||
filters: JSON.stringify({
|
||||
OR: [
|
||||
{ key: "category", value: "technology", negate: false },
|
||||
{ key: "category", value: "science", negate: false }
|
||||
]
|
||||
})
|
||||
```
|
||||
</ParamField>
|
||||
|
||||
## Memory Search Parameters (POST `/v4/search`)
|
||||
|
||||
These parameters are specific to `client.search.memories()`:
|
||||
|
||||
<ParamField query="threshold" type="number" range="0-1" default="0.5">
|
||||
**Sensitivity for memory selection**
|
||||
|
||||
Controls which memories are returned based on similarity:
|
||||
- **0.0** = Return more memories (broad search)
|
||||
- **1.0** = Return only highly similar memories (precise search)
|
||||
|
||||
```typescript
|
||||
threshold: 0.3 // Broader memory search
|
||||
threshold: 0.8 // Only very similar memories
|
||||
```
|
||||
</ParamField>
|
||||
|
||||
<ParamField query="searchMode" type="string" default="memories">
|
||||
**Search mode - memories only or hybrid search**
|
||||
|
||||
Controls whether to search only memories or also include document chunks:
|
||||
- **`"memories"`** (default): Searches only memory entries. Returns results with `memory` field.
|
||||
- **`"hybrid"`**: Searches memories first, then falls back to document chunks if needed. Returns mixed results with either `memory` field (for memory results) or `chunk` field (for chunk results).
|
||||
|
||||
<Note>
|
||||
In hybrid mode, results are automatically merged and deduplicated. Results contain objects with either a `memory` key (for memory results) or a `chunk` key (for chunk results from document search).
|
||||
</Note>
|
||||
|
||||
```typescript
|
||||
searchMode: "memories" // Only search memories (default)
|
||||
searchMode: "hybrid" // Search memories + fallback to chunks
|
||||
```
|
||||
|
||||
**When to use hybrid mode:**
|
||||
- When you want comprehensive search across both memories and documents
|
||||
- When memories might not exist for certain queries but document content is available
|
||||
- When you need the flexibility to get either memory or document chunk results
|
||||
</ParamField>
|
||||
|
||||
<ParamField query="containerTag" type="string">
|
||||
**Filter by single container tag**
|
||||
|
||||
Note: Memory search uses `containerTag` (singular) while document search uses `containerTags` (plural array).
|
||||
|
||||
```typescript
|
||||
containerTag: "user_123" // Single tag for memory search
|
||||
```
|
||||
</ParamField>
|
||||
|
||||
<ParamField query="include" type="object">
|
||||
**Control what additional data to include**
|
||||
|
||||
Object specifying what contextual information to include with memory results.
|
||||
|
||||
<ParamField query="include.documents" type="boolean" default="false">
|
||||
Include associated documents for each memory
|
||||
</ParamField>
|
||||
|
||||
<ParamField query="include.relatedMemories" type="boolean" default="false">
|
||||
Include parent and child memories (contextual relationships)
|
||||
</ParamField>
|
||||
|
||||
<ParamField query="include.summaries" type="boolean" default="false">
|
||||
Include memory summaries
|
||||
</ParamField>
|
||||
|
||||
```typescript
|
||||
include: {
|
||||
documents: true, // Show related documents
|
||||
relatedMemories: true, // Show parent/child memories
|
||||
summaries: true // Include summaries
|
||||
}
|
||||
```
|
||||
</ParamField>
|
||||
|
|
@ -1,440 +0,0 @@
|
|||
---
|
||||
title: "Query Rewriting"
|
||||
description: "Improve search accuracy with automatic query expansion and rewriting"
|
||||
---
|
||||
|
||||
|
||||

|
||||
|
||||
Query rewriting automatically generates multiple variations of your search query to improve result coverage and accuracy. Supermemory creates several rewrites, searches through all of them, then merges and deduplicates the results.
|
||||
|
||||
## How Query Rewriting Works
|
||||
|
||||
When you enable `rewriteQuery: true`, Supermemory:
|
||||
|
||||
1. **Analyzes your original query** for intent and key concepts
|
||||
2. **Generates multiple rewrites** with different phrasings and synonyms
|
||||
3. **Executes searches** for both original and rewritten queries in parallel
|
||||
4. **Merges and deduplicates** results from all queries
|
||||
5. **Returns unified results** ranked by relevance
|
||||
|
||||
This process adds ~400ms latency but significantly improves result quality, especially for:
|
||||
- **Natural language questions** ("How do neural networks learn?")
|
||||
- **Ambiguous terms** that could have multiple meanings
|
||||
- **Complex queries** with multiple concepts
|
||||
- **Domain-specific terminology** that might have synonyms
|
||||
|
||||
## Basic Query Rewriting
|
||||
|
||||
<Tabs>
|
||||
<Tab title="TypeScript">
|
||||
```typescript
|
||||
import Supermemory from 'supermemory';
|
||||
|
||||
const client = new Supermemory({
|
||||
apiKey: process.env.SUPERMEMORY_API_KEY!
|
||||
});
|
||||
|
||||
// Without query rewriting
|
||||
const basicResults = await client.search.documents({
|
||||
q: "How do transformers work in AI?",
|
||||
rewriteQuery: false,
|
||||
limit: 5
|
||||
});
|
||||
|
||||
// With query rewriting - generates multiple query variations
|
||||
const rewrittenResults = await client.search.documents({
|
||||
q: "How do transformers work in AI?",
|
||||
rewriteQuery: true,
|
||||
limit: 5
|
||||
});
|
||||
|
||||
console.log(`Basic search: ${basicResults.total} results`);
|
||||
console.log(`Rewritten search: ${rewrittenResults.total} results`);
|
||||
```
|
||||
</Tab>
|
||||
<Tab title="Python">
|
||||
```python
|
||||
from supermemory import Supermemory
|
||||
import os
|
||||
|
||||
client = Supermemory(api_key=os.environ.get("SUPERMEMORY_API_KEY"))
|
||||
|
||||
# Without query rewriting
|
||||
basic_results = client.search.documents(
|
||||
q="How do transformers work in AI?",
|
||||
rewrite_query=False,
|
||||
limit=5
|
||||
)
|
||||
|
||||
# With query rewriting - generates multiple query variations
|
||||
rewritten_results = client.search.documents(
|
||||
q="How do transformers work in AI?",
|
||||
rewrite_query=True,
|
||||
limit=5
|
||||
)
|
||||
|
||||
print(f"Basic search: {basic_results.total} results")
|
||||
print(f"Rewritten search: {rewritten_results.total} results")
|
||||
```
|
||||
</Tab>
|
||||
<Tab title="cURL">
|
||||
```bash
|
||||
# Without query rewriting
|
||||
echo "Basic search:"
|
||||
curl -X POST "https://api.supermemory.ai/v3/search" \
|
||||
-H "Authorization: Bearer $SUPERMEMORY_API_KEY" \
|
||||
-H "Content-Type: application/json" \
|
||||
-d '{
|
||||
"q": "How do transformers work in AI?",
|
||||
"rewriteQuery": false,
|
||||
"limit": 5
|
||||
}' | jq '.total'
|
||||
|
||||
# With query rewriting
|
||||
echo "Rewritten search:"
|
||||
curl -X POST "https://api.supermemory.ai/v3/search" \
|
||||
-H "Authorization: Bearer $SUPERMEMORY_API_KEY" \
|
||||
-H "Content-Type: application/json" \
|
||||
-d '{
|
||||
"q": "How do transformers work in AI?",
|
||||
"rewriteQuery": true,
|
||||
"limit": 5
|
||||
}' | jq '.total'
|
||||
```
|
||||
</Tab>
|
||||
</Tabs>
|
||||
|
||||
**Sample Output Comparison:**
|
||||
```json
|
||||
// Without rewriting: 3 results
|
||||
{
|
||||
"results": [...],
|
||||
"total": 3,
|
||||
"timing": 120
|
||||
}
|
||||
|
||||
// With rewriting: 8 results (found more relevant content)
|
||||
{
|
||||
"results": [...],
|
||||
"total": 8,
|
||||
"timing": 520 // +400ms for query processing
|
||||
}
|
||||
```
|
||||
|
||||
## Natural Language Questions
|
||||
|
||||
Query rewriting excels at converting conversational questions into effective search queries:
|
||||
|
||||
<Tabs>
|
||||
<Tab title="TypeScript">
|
||||
```typescript
|
||||
// Natural language question
|
||||
const results = await client.search.documents({
|
||||
q: "What are the best practices for training deep learning models?",
|
||||
rewriteQuery: true,
|
||||
limit: 10
|
||||
});
|
||||
|
||||
// The system might generate rewrites like:
|
||||
// - "deep learning model training best practices"
|
||||
// - "neural network training optimization techniques"
|
||||
// - "machine learning model training guidelines"
|
||||
// - "deep learning training methodology"
|
||||
```
|
||||
</Tab>
|
||||
<Tab title="Python">
|
||||
```python
|
||||
# Natural language question
|
||||
results = client.search.documents(
|
||||
q="What are the best practices for training deep learning models?",
|
||||
rewrite_query=True,
|
||||
limit=10
|
||||
)
|
||||
|
||||
# The system might generate rewrites like:
|
||||
# - "deep learning model training best practices"
|
||||
# - "neural network training optimization techniques"
|
||||
# - "machine learning model training guidelines"
|
||||
# - "deep learning training methodology"
|
||||
```
|
||||
</Tab>
|
||||
<Tab title="cURL">
|
||||
```bash
|
||||
curl -X POST "https://api.supermemory.ai/v3/search" \
|
||||
-H "Authorization: Bearer $SUPERMEMORY_API_KEY" \
|
||||
-H "Content-Type: application/json" \
|
||||
-d '{
|
||||
"q": "What are the best practices for training deep learning models?",
|
||||
"rewriteQuery": true,
|
||||
"limit": 10
|
||||
}'
|
||||
```
|
||||
</Tab>
|
||||
</Tabs>
|
||||
|
||||
**Sample Output:**
|
||||
```json
|
||||
{
|
||||
"results": [
|
||||
{
|
||||
"documentId": "doc_123",
|
||||
"title": "Deep Learning Training Guide",
|
||||
"score": 0.92,
|
||||
"chunks": [
|
||||
{
|
||||
"content": "Best practices for training deep neural networks include proper weight initialization, learning rate scheduling, and regularization techniques...",
|
||||
"score": 0.89,
|
||||
"isRelevant": true
|
||||
}
|
||||
]
|
||||
},
|
||||
{
|
||||
"documentId": "doc_456",
|
||||
"title": "Neural Network Optimization",
|
||||
"score": 0.87,
|
||||
"chunks": [
|
||||
{
|
||||
"content": "Effective training methodologies involve batch normalization, dropout, and gradient clipping to prevent overfitting...",
|
||||
"score": 0.85,
|
||||
"isRelevant": true
|
||||
}
|
||||
]
|
||||
}
|
||||
],
|
||||
"total": 12,
|
||||
"timing": 445
|
||||
}
|
||||
```
|
||||
|
||||
## Technical Term Expansion
|
||||
|
||||
Query rewriting helps find content using different technical terminologies:
|
||||
|
||||
<Tabs>
|
||||
<Tab title="TypeScript">
|
||||
```typescript
|
||||
// Original query with specific terminology
|
||||
const results = await client.search.documents({
|
||||
q: "CNN architecture patterns",
|
||||
rewriteQuery: true,
|
||||
containerTags: ["research"],
|
||||
limit: 8
|
||||
});
|
||||
|
||||
// System expands to include:
|
||||
// - "convolutional neural network architecture"
|
||||
// - "CNN design patterns"
|
||||
// - "convolutional network structures"
|
||||
// - "CNN architectural components"
|
||||
```
|
||||
</Tab>
|
||||
<Tab title="Python">
|
||||
```python
|
||||
# Original query with specific terminology
|
||||
results = client.search.documents(
|
||||
q="CNN architecture patterns",
|
||||
rewrite_query=True,
|
||||
container_tags=["research"],
|
||||
limit=8
|
||||
)
|
||||
|
||||
# System expands to include:
|
||||
# - "convolutional neural network architecture"
|
||||
# - "CNN design patterns"
|
||||
# - "convolutional network structures"
|
||||
# - "CNN architectural components"
|
||||
```
|
||||
</Tab>
|
||||
<Tab title="cURL">
|
||||
```bash
|
||||
curl -X POST "https://api.supermemory.ai/v3/search" \
|
||||
-H "Authorization: Bearer $SUPERMEMORY_API_KEY" \
|
||||
-H "Content-Type: application/json" \
|
||||
-d '{
|
||||
"q": "CNN architecture patterns",
|
||||
"rewriteQuery": true,
|
||||
"containerTags": ["research"],
|
||||
"limit": 8
|
||||
}'
|
||||
```
|
||||
</Tab>
|
||||
</Tabs>
|
||||
|
||||
**Sample Output:**
|
||||
```json
|
||||
{
|
||||
"results": [
|
||||
{
|
||||
"documentId": "doc_789",
|
||||
"title": "Convolutional Neural Network Architectures",
|
||||
"score": 0.94,
|
||||
"chunks": [
|
||||
{
|
||||
"content": "Modern CNN architectures like ResNet and DenseNet utilize skip connections to address the vanishing gradient problem...",
|
||||
"score": 0.91,
|
||||
"isRelevant": true
|
||||
}
|
||||
]
|
||||
},
|
||||
{
|
||||
"documentId": "doc_101",
|
||||
"title": "Deep Learning Design Patterns",
|
||||
"score": 0.88,
|
||||
"chunks": [
|
||||
{
|
||||
"content": "Convolutional layers followed by pooling operations form the fundamental building blocks of CNN architectures...",
|
||||
"score": 0.86,
|
||||
"isRelevant": true
|
||||
}
|
||||
]
|
||||
}
|
||||
],
|
||||
"total": 15,
|
||||
"timing": 478
|
||||
}
|
||||
```
|
||||
|
||||
## Memory Search with Query Rewriting
|
||||
|
||||
Query rewriting works with both document and memory search:
|
||||
|
||||
<Tabs>
|
||||
<Tab title="TypeScript">
|
||||
```typescript
|
||||
// Memory search with query rewriting
|
||||
const memoryResults = await client.search.memories({
|
||||
q: "explain quantum entanglement simply",
|
||||
rewriteQuery: true,
|
||||
containerTag: "physics_notes",
|
||||
limit: 5
|
||||
});
|
||||
|
||||
// Generates variations like:
|
||||
// - "quantum entanglement explanation"
|
||||
// - "what is quantum entanglement"
|
||||
// - "quantum entanglement basics"
|
||||
// - "simple quantum entanglement description"
|
||||
```
|
||||
</Tab>
|
||||
<Tab title="Python">
|
||||
```python
|
||||
# Memory search with query rewriting
|
||||
memory_results = client.search.memories(
|
||||
q="explain quantum entanglement simply",
|
||||
rewrite_query=True,
|
||||
container_tag="physics_notes",
|
||||
limit=5
|
||||
)
|
||||
|
||||
# Generates variations like:
|
||||
# - "quantum entanglement explanation"
|
||||
# - "what is quantum entanglement"
|
||||
# - "quantum entanglement basics"
|
||||
# - "simple quantum entanglement description"
|
||||
```
|
||||
</Tab>
|
||||
<Tab title="cURL">
|
||||
```bash
|
||||
curl -X POST "https://api.supermemory.ai/v4/search" \
|
||||
-H "Authorization: Bearer $SUPERMEMORY_API_KEY" \
|
||||
-H "Content-Type: application/json" \
|
||||
-d '{
|
||||
"q": "explain quantum entanglement simply",
|
||||
"rewriteQuery": true,
|
||||
"containerTag": "physics_notes",
|
||||
"limit": 5
|
||||
}'
|
||||
```
|
||||
</Tab>
|
||||
</Tabs>
|
||||
|
||||
**Sample Output:**
|
||||
```json
|
||||
{
|
||||
"results": [
|
||||
{
|
||||
"id": "mem_456",
|
||||
"memory": "Quantum entanglement is a phenomenon where two particles become connected in such a way that measuring one instantly affects the other, regardless of distance. Think of it like having two magical coins that always land on opposite sides.",
|
||||
"similarity": 0.91,
|
||||
"title": "Simple Quantum Entanglement Explanation",
|
||||
"metadata": {
|
||||
"topic": "quantum-physics",
|
||||
"difficulty": "beginner"
|
||||
}
|
||||
},
|
||||
{
|
||||
"id": "mem_789",
|
||||
"memory": "Einstein called quantum entanglement 'spooky action at a distance' because entangled particles seem to communicate instantaneously across vast distances, challenging our understanding of locality in physics.",
|
||||
"similarity": 0.87,
|
||||
"title": "Einstein's View on Entanglement"
|
||||
}
|
||||
],
|
||||
"total": 7,
|
||||
"timing": 412
|
||||
}
|
||||
```
|
||||
|
||||
## Complex Multi-Concept Queries
|
||||
|
||||
Query rewriting excels at handling queries with multiple concepts:
|
||||
|
||||
<Tabs>
|
||||
<Tab title="TypeScript">
|
||||
```typescript
|
||||
const results = await client.search.documents({
|
||||
q: "machine learning bias fairness algorithmic discrimination",
|
||||
rewriteQuery: true,
|
||||
filters: {
|
||||
AND: [
|
||||
{ key: "category", value: "ethics", negate: false }
|
||||
]
|
||||
},
|
||||
limit: 10
|
||||
});
|
||||
|
||||
// Breaks down into focused rewrites:
|
||||
// - "machine learning bias detection"
|
||||
// - "algorithmic fairness in AI"
|
||||
// - "discrimination in machine learning algorithms"
|
||||
// - "bias mitigation techniques ML"
|
||||
```
|
||||
</Tab>
|
||||
<Tab title="Python">
|
||||
```python
|
||||
results = client.search.documents(
|
||||
q="machine learning bias fairness algorithmic discrimination",
|
||||
rewrite_query=True,
|
||||
filters={
|
||||
"AND": [
|
||||
{"key": "category", "value": "ethics", "negate": False}
|
||||
]
|
||||
},
|
||||
limit=10
|
||||
)
|
||||
|
||||
# Breaks down into focused rewrites:
|
||||
# - "machine learning bias detection"
|
||||
# - "algorithmic fairness in AI"
|
||||
# - "discrimination in machine learning algorithms"
|
||||
# - "bias mitigation techniques ML"
|
||||
```
|
||||
</Tab>
|
||||
<Tab title="cURL">
|
||||
```bash
|
||||
curl -X POST "https://api.supermemory.ai/v3/search" \
|
||||
-H "Authorization: Bearer $SUPERMEMORY_API_KEY" \
|
||||
-H "Content-Type: application/json" \
|
||||
-d '{
|
||||
"q": "machine learning bias fairness algorithmic discrimination",
|
||||
"rewriteQuery": true,
|
||||
"filters": {
|
||||
"AND": [
|
||||
{"key": "category", "value": "ethics", "negate": false}
|
||||
]
|
||||
},
|
||||
"limit": 10
|
||||
}'
|
||||
```
|
||||
</Tab>
|
||||
</Tabs>
|
||||
|
|
@ -1,387 +0,0 @@
|
|||
---
|
||||
title: "Reranking"
|
||||
description: "Improve result relevance with secondary ranking algorithms"
|
||||
---
|
||||
|
||||
|
||||
Reranking applies a secondary ranking algorithm to improve the relevance order of search results. After the initial search returns results, the reranker analyzes the relationship between your query and each result to provide better ordering.
|
||||
|
||||
## How Reranking Works
|
||||
|
||||
Supermemory's reranking process:
|
||||
|
||||
1. **Initial search** returns results using standard semantic similarity
|
||||
2. **Reranker model** analyzes query-result pairs
|
||||
3. **Scores are recalculated** based on deeper semantic understanding
|
||||
4. **Results are reordered** by the new relevance scores
|
||||
5. **Final results** maintain the same structure but with improved ordering
|
||||
|
||||
The reranker is particularly effective at:
|
||||
- **Understanding context** and nuanced relationships
|
||||
- **Handling ambiguous queries** with multiple possible meanings
|
||||
- **Improving precision** for complex technical topics
|
||||
- **Better ranking** when results have similar initial scores
|
||||
|
||||
## Basic Reranking Comparison
|
||||
|
||||
<Tabs>
|
||||
<Tab title="TypeScript">
|
||||
```typescript
|
||||
import Supermemory from 'supermemory';
|
||||
|
||||
const client = new Supermemory({
|
||||
apiKey: process.env.SUPERMEMORY_API_KEY!
|
||||
});
|
||||
|
||||
// Search without reranking
|
||||
const standardResults = await client.search.documents({
|
||||
q: "neural network optimization techniques",
|
||||
rerank: false,
|
||||
limit: 5
|
||||
});
|
||||
|
||||
// Search with reranking
|
||||
const rerankedResults = await client.search.documents({
|
||||
q: "neural network optimization techniques",
|
||||
rerank: true,
|
||||
limit: 5
|
||||
});
|
||||
|
||||
console.log("Standard top result:", standardResults.results[0].score);
|
||||
console.log("Reranked top result:", rerankedResults.results[0].score);
|
||||
```
|
||||
</Tab>
|
||||
<Tab title="Python">
|
||||
```python
|
||||
from supermemory import Supermemory
|
||||
import os
|
||||
|
||||
client = Supermemory(api_key=os.environ.get("SUPERMEMORY_API_KEY"))
|
||||
|
||||
# Search without reranking
|
||||
standard_results = client.search.documents(
|
||||
q="neural network optimization techniques",
|
||||
rerank=False,
|
||||
limit=5
|
||||
)
|
||||
|
||||
# Search with reranking
|
||||
reranked_results = client.search.documents(
|
||||
q="neural network optimization techniques",
|
||||
rerank=True,
|
||||
limit=5
|
||||
)
|
||||
|
||||
print("Standard top result:", standard_results.results[0].score)
|
||||
print("Reranked top result:", reranked_results.results[0].score)
|
||||
```
|
||||
</Tab>
|
||||
<Tab title="cURL">
|
||||
```bash
|
||||
# Without reranking
|
||||
echo "Standard ranking:"
|
||||
curl -X POST "https://api.supermemory.ai/v3/search" \
|
||||
-H "Authorization: Bearer $SUPERMEMORY_API_KEY" \
|
||||
-H "Content-Type: application/json" \
|
||||
-d '{
|
||||
"q": "neural network optimization techniques",
|
||||
"rerank": false,
|
||||
"limit": 3
|
||||
}' | jq '.results[0] | {title, score}'
|
||||
|
||||
# With reranking
|
||||
echo "Reranked results:"
|
||||
curl -X POST "https://api.supermemory.ai/v3/search" \
|
||||
-H "Authorization: Bearer $SUPERMEMORY_API_KEY" \
|
||||
-H "Content-Type: application/json" \
|
||||
-d '{
|
||||
"q": "neural network optimization techniques",
|
||||
"rerank": true,
|
||||
"limit": 3
|
||||
}' | jq '.results[0] | {title, score}'
|
||||
```
|
||||
</Tab>
|
||||
</Tabs>
|
||||
|
||||
**Sample Output Comparison:**
|
||||
|
||||
```json
|
||||
// Without reranking - results ordered by semantic similarity
|
||||
{
|
||||
"results": [
|
||||
{
|
||||
"title": "Deep Learning Optimization Methods",
|
||||
"score": 0.82,
|
||||
"chunks": [
|
||||
{
|
||||
"content": "Various optimization algorithms like Adam, RMSprop, and SGD are used in neural network training...",
|
||||
"score": 0.79
|
||||
}
|
||||
]
|
||||
},
|
||||
{
|
||||
"title": "Neural Network Training Techniques",
|
||||
"score": 0.81,
|
||||
"chunks": [
|
||||
{
|
||||
"content": "Batch normalization and dropout are common regularization techniques for neural networks...",
|
||||
"score": 0.78
|
||||
}
|
||||
]
|
||||
}
|
||||
],
|
||||
"timing": 145
|
||||
}
|
||||
|
||||
// With reranking - results reordered by contextual relevance
|
||||
{
|
||||
"results": [
|
||||
{
|
||||
"title": "Neural Network Training Techniques",
|
||||
"score": 0.89, // Boosted by reranker
|
||||
"chunks": [
|
||||
{
|
||||
"content": "Batch normalization and dropout are common regularization techniques for neural networks...",
|
||||
"score": 0.85
|
||||
}
|
||||
]
|
||||
},
|
||||
{
|
||||
"title": "Deep Learning Optimization Methods",
|
||||
"score": 0.86, // Slightly adjusted
|
||||
"chunks": [
|
||||
{
|
||||
"content": "Various optimization algorithms like Adam, RMSprop, and SGD are used in neural network training...",
|
||||
"score": 0.83
|
||||
}
|
||||
]
|
||||
}
|
||||
],
|
||||
"timing": 267 // Additional ~120ms for reranking
|
||||
}
|
||||
```
|
||||
|
||||
## Complex Query Reranking
|
||||
|
||||
Reranking excels with complex, multi-faceted queries:
|
||||
|
||||
<Tabs>
|
||||
<Tab title="TypeScript">
|
||||
```typescript
|
||||
const results = await client.search.documents({
|
||||
q: "sustainable machine learning carbon footprint energy efficiency",
|
||||
rerank: true,
|
||||
containerTags: ["research", "sustainability"],
|
||||
limit: 8
|
||||
});
|
||||
|
||||
// Reranker understands the connection between:
|
||||
// - Machine learning computational costs
|
||||
// - Environmental impact of AI training
|
||||
// - Energy-efficient model architectures
|
||||
// - Green computing practices in ML
|
||||
```
|
||||
</Tab>
|
||||
<Tab title="Python">
|
||||
```python
|
||||
results = client.search.documents(
|
||||
q="sustainable machine learning carbon footprint energy efficiency",
|
||||
rerank=True,
|
||||
container_tags=["research", "sustainability"],
|
||||
limit=8
|
||||
)
|
||||
|
||||
# Reranker understands the connection between:
|
||||
# - Machine learning computational costs
|
||||
# - Environmental impact of AI training
|
||||
# - Energy-efficient model architectures
|
||||
# - Green computing practices in ML
|
||||
```
|
||||
</Tab>
|
||||
<Tab title="cURL">
|
||||
```bash
|
||||
curl -X POST "https://api.supermemory.ai/v3/search" \
|
||||
-H "Authorization: Bearer $SUPERMEMORY_API_KEY" \
|
||||
-H "Content-Type: application/json" \
|
||||
-d '{
|
||||
"q": "sustainable machine learning carbon footprint energy efficiency",
|
||||
"rerank": true,
|
||||
"containerTags": ["research", "sustainability"],
|
||||
"limit": 8
|
||||
}'
|
||||
```
|
||||
</Tab>
|
||||
</Tabs>
|
||||
|
||||
**Sample Output:**
|
||||
```json
|
||||
{
|
||||
"results": [
|
||||
{
|
||||
"documentId": "doc_green_ai",
|
||||
"title": "Green AI: Reducing the Carbon Footprint of Machine Learning",
|
||||
"score": 0.94, // Highly relevant after reranking
|
||||
"chunks": [
|
||||
{
|
||||
"content": "Training large neural networks can consume as much energy as several cars over their lifetime. Sustainable ML practices focus on model efficiency, pruning, and quantization to reduce computational demands...",
|
||||
"score": 0.92,
|
||||
"isRelevant": true
|
||||
}
|
||||
]
|
||||
},
|
||||
{
|
||||
"documentId": "doc_efficient_models",
|
||||
"title": "Energy-Efficient Neural Network Architectures",
|
||||
"score": 0.91, // Boosted for strong topical relevance
|
||||
"chunks": [
|
||||
{
|
||||
"content": "MobileNets and EfficientNets are designed specifically for energy-constrained environments, achieving high accuracy with minimal computational overhead...",
|
||||
"score": 0.88,
|
||||
"isRelevant": true
|
||||
}
|
||||
]
|
||||
}
|
||||
],
|
||||
"total": 12,
|
||||
"timing": 298
|
||||
}
|
||||
```
|
||||
|
||||
## Memory Search Reranking
|
||||
|
||||
Reranking also improves memory search results:
|
||||
|
||||
<Tabs>
|
||||
<Tab title="TypeScript">
|
||||
```typescript
|
||||
const memoryResults = await client.search.memories({
|
||||
q: "explain transformer architecture attention mechanism",
|
||||
rerank: true,
|
||||
containerTag: "ai_notes",
|
||||
threshold: 0.6,
|
||||
limit: 5
|
||||
});
|
||||
|
||||
// Reranker identifies memories that best explain
|
||||
// the relationship between transformers and attention
|
||||
```
|
||||
</Tab>
|
||||
<Tab title="Python">
|
||||
```python
|
||||
memory_results = client.search.memories(
|
||||
q="explain transformer architecture attention mechanism",
|
||||
rerank=True,
|
||||
container_tag="ai_notes",
|
||||
threshold=0.6,
|
||||
limit=5
|
||||
)
|
||||
|
||||
# Reranker identifies memories that best explain
|
||||
# the relationship between transformers and attention
|
||||
```
|
||||
</Tab>
|
||||
<Tab title="cURL">
|
||||
```bash
|
||||
curl -X POST "https://api.supermemory.ai/v4/search" \
|
||||
-H "Authorization: Bearer $SUPERMEMORY_API_KEY" \
|
||||
-H "Content-Type: application/json" \
|
||||
-d '{
|
||||
"q": "explain transformer architecture attention mechanism",
|
||||
"rerank": true,
|
||||
"containerTag": "ai_notes",
|
||||
"threshold": 0.6,
|
||||
"limit": 5
|
||||
}'
|
||||
```
|
||||
</Tab>
|
||||
</Tabs>
|
||||
|
||||
**Sample Output:**
|
||||
```json
|
||||
{
|
||||
"results": [
|
||||
{
|
||||
"id": "mem_transformer_intro",
|
||||
"memory": "The transformer architecture revolutionized NLP by replacing recurrent layers with self-attention mechanisms. The attention mechanism allows the model to focus on different parts of the input sequence when processing each token, enabling parallel processing and better long-range dependency modeling.",
|
||||
"similarity": 0.93, // Reranked higher for comprehensive explanation
|
||||
"title": "Transformer Architecture Overview",
|
||||
"metadata": {
|
||||
"topic": "deep-learning",
|
||||
"subtopic": "transformers"
|
||||
}
|
||||
},
|
||||
{
|
||||
"id": "mem_attention_detail",
|
||||
"memory": "Self-attention computes attention weights by taking dot products between query, key, and value vectors derived from the input embeddings. This allows each position to attend to all positions in the previous layer, capturing complex relationships in the data.",
|
||||
"similarity": 0.91, // Boosted for technical detail
|
||||
"title": "Self-Attention Mechanism Details"
|
||||
}
|
||||
],
|
||||
"total": 8,
|
||||
"timing": 198
|
||||
}
|
||||
```
|
||||
|
||||
## Domain-Specific Reranking
|
||||
|
||||
Reranking understands domain-specific relationships:
|
||||
|
||||
<Tabs>
|
||||
<Tab title="TypeScript">
|
||||
```typescript
|
||||
// Medical domain query
|
||||
const medicalResults = await client.search.documents({
|
||||
q: "diabetes treatment insulin resistance metformin",
|
||||
rerank: true,
|
||||
filters: {
|
||||
AND: [
|
||||
{ key: "domain", value: "medical", negate: false }
|
||||
]
|
||||
},
|
||||
limit: 10
|
||||
});
|
||||
|
||||
// Reranker understands medical relationships:
|
||||
// - Diabetes types and treatments
|
||||
// - Insulin resistance mechanisms
|
||||
// - Metformin's role in diabetes management
|
||||
```
|
||||
</Tab>
|
||||
<Tab title="Python">
|
||||
```python
|
||||
# Medical domain query
|
||||
medical_results = client.search.documents(
|
||||
q="diabetes treatment insulin resistance metformin",
|
||||
rerank=True,
|
||||
filters={
|
||||
"AND": [
|
||||
{"key": "domain", "value": "medical", "negate": False}
|
||||
]
|
||||
},
|
||||
limit=10
|
||||
)
|
||||
|
||||
# Reranker understands medical relationships:
|
||||
# - Diabetes types and treatments
|
||||
# - Insulin resistance mechanisms
|
||||
# - Metformin's role in diabetes management
|
||||
```
|
||||
</Tab>
|
||||
<Tab title="cURL">
|
||||
```bash
|
||||
curl -X POST "https://api.supermemory.ai/v3/search" \
|
||||
-H "Authorization: Bearer $SUPERMEMORY_API_KEY" \
|
||||
-H "Content-Type: application/json" \
|
||||
-d '{
|
||||
"q": "diabetes treatment insulin resistance metformin",
|
||||
"rerank": true,
|
||||
"filters": {
|
||||
"AND": [
|
||||
{"key": "domain", "value": "medical", "negate": false}
|
||||
]
|
||||
},
|
||||
"limit": 10
|
||||
}'
|
||||
```
|
||||
</Tab>
|
||||
</Tabs>
|
||||
|
|
@ -1,354 +0,0 @@
|
|||
---
|
||||
title: "Response Schema"
|
||||
description: "Complete response structure for all search endpoints with scoring details"
|
||||
---
|
||||
|
||||
|
||||
## Document Search Response (POST `/v3/search`)
|
||||
|
||||
Response from `client.search.documents()` and `client.search.execute()`:
|
||||
|
||||
```json
|
||||
{
|
||||
"results": [
|
||||
{
|
||||
"documentId": "doc_abc123",
|
||||
"title": "Machine Learning Fundamentals",
|
||||
"type": "pdf",
|
||||
"score": 0.89,
|
||||
"chunks": [
|
||||
{
|
||||
"content": "Machine learning is a subset of artificial intelligence...",
|
||||
"score": 0.95,
|
||||
"isRelevant": true
|
||||
}
|
||||
],
|
||||
"metadata": {
|
||||
"category": "education",
|
||||
"author": "Dr. Smith",
|
||||
"difficulty": "beginner"
|
||||
},
|
||||
"createdAt": "2024-01-15T10:30:00Z",
|
||||
"updatedAt": "2024-01-20T14:45:00Z"
|
||||
}
|
||||
],
|
||||
"timing": 187,
|
||||
"total": 1
|
||||
}
|
||||
```
|
||||
|
||||
### Document Result Fields
|
||||
|
||||
<ResponseField name="documentId" type="string">
|
||||
Unique identifier for the document containing the matching chunks.
|
||||
</ResponseField>
|
||||
|
||||
<ResponseField name="title" type="string | null">
|
||||
Document title if available. May be null for documents without titles.
|
||||
</ResponseField>
|
||||
|
||||
<ResponseField name="type" type="string | null">
|
||||
Document type (e.g., "pdf", "text", "webpage", "notion_doc"). May be null if not specified.
|
||||
</ResponseField>
|
||||
|
||||
<ResponseField name="score" type="number" range="0-1">
|
||||
**Overall document relevance score**. Combines semantic similarity, keyword matching, and metadata relevance.
|
||||
|
||||
- **0.9-1.0**: Extremely relevant
|
||||
- **0.7-0.9**: Highly relevant
|
||||
- **0.5-0.7**: Moderately relevant
|
||||
- **0.3-0.5**: Somewhat relevant
|
||||
- **0.0-0.3**: Marginally relevant
|
||||
</ResponseField>
|
||||
|
||||
<ResponseField name="chunks" type="Array<Chunk>">
|
||||
Array of matching text chunks from the document. Each chunk represents a portion of the document that matched your query.
|
||||
|
||||
<ResponseField name="chunks[].content" type="string">
|
||||
The actual text content of the matching chunk. May include context from surrounding chunks unless `onlyMatchingChunks=true`.
|
||||
</ResponseField>
|
||||
|
||||
<ResponseField name="chunks[].score" type="number" range="0-1">
|
||||
**Chunk-specific similarity score**. How well this specific chunk matches your query.
|
||||
</ResponseField>
|
||||
|
||||
<ResponseField name="chunks[].isRelevant" type="boolean">
|
||||
Whether this chunk passed the `chunkThreshold`. `true` means the chunk is above the threshold, `false` means it's included for context only.
|
||||
</ResponseField>
|
||||
</ResponseField>
|
||||
|
||||
<ResponseField name="metadata" type="object | null">
|
||||
Document metadata as key-value pairs. Structure depends on what was stored with the document.
|
||||
|
||||
```json
|
||||
{
|
||||
"category": "tutorial",
|
||||
"language": "python",
|
||||
"difficulty": "intermediate",
|
||||
"tags": "web-development,backend"
|
||||
}
|
||||
```
|
||||
</ResponseField>
|
||||
|
||||
<ResponseField name="createdAt" type="string">
|
||||
ISO 8601 timestamp when the document was created.
|
||||
</ResponseField>
|
||||
|
||||
<ResponseField name="updatedAt" type="string">
|
||||
ISO 8601 timestamp when the document was last updated.
|
||||
</ResponseField>
|
||||
|
||||
<ResponseField name="content" type="string | null" optional>
|
||||
**Full document content**. Only included when `includeFullDocs=true`. Can be very large.
|
||||
|
||||
<Warning>
|
||||
Full document content can make responses extremely large. Use with appropriate limits and only when necessary.
|
||||
</Warning>
|
||||
</ResponseField>
|
||||
|
||||
<ResponseField name="summary" type="string | null" optional>
|
||||
**AI-generated document summary**. Only included when `includeSummary=true`. Provides a concise overview of the document.
|
||||
</ResponseField>
|
||||
|
||||
## Memory Search Response
|
||||
|
||||
Response from `client.search.memories()`:
|
||||
|
||||
When `searchMode="memories"` (default), all results are memory entries:
|
||||
|
||||
```json
|
||||
{
|
||||
"results": [
|
||||
{
|
||||
"id": "mem_xyz789",
|
||||
"memory": "Complete memory content about quantum computing applications...",
|
||||
"similarity": 0.87,
|
||||
"metadata": {
|
||||
"category": "research",
|
||||
"topic": "quantum-computing"
|
||||
},
|
||||
"updatedAt": "2024-01-18T09:15:00Z",
|
||||
"version": 3,
|
||||
"context": {
|
||||
"parents": [
|
||||
{
|
||||
"memory": "Earlier discussion about quantum theory basics...",
|
||||
"relation": "extends",
|
||||
"version": 2,
|
||||
"updatedAt": "2024-01-17T16:30:00Z"
|
||||
}
|
||||
],
|
||||
"children": [
|
||||
{
|
||||
"memory": "Follow-up questions about quantum algorithms...",
|
||||
"relation": "derives",
|
||||
"version": 4,
|
||||
"updatedAt": "2024-01-19T11:20:00Z"
|
||||
}
|
||||
]
|
||||
},
|
||||
"documents": [
|
||||
{
|
||||
"id": "doc_quantum_paper",
|
||||
"title": "Quantum Computing Applications",
|
||||
"type": "pdf",
|
||||
"createdAt": "2024-01-10T08:00:00Z"
|
||||
}
|
||||
]
|
||||
}
|
||||
],
|
||||
"timing": 156,
|
||||
"total": 1
|
||||
}
|
||||
```
|
||||
|
||||
When `searchMode="hybrid"`, results can contain both memory entries and document chunks. **Memory results have a `memory` key, chunk results have a `chunk` key:**
|
||||
|
||||
```json
|
||||
{
|
||||
"results": [
|
||||
{
|
||||
"id": "mem_xyz789",
|
||||
"memory": "Complete memory content about quantum computing applications...",
|
||||
"similarity": 0.87,
|
||||
"metadata": {
|
||||
"category": "research",
|
||||
"topic": "quantum-computing"
|
||||
},
|
||||
"updatedAt": "2024-01-18T09:15:00Z",
|
||||
"version": 3,
|
||||
"context": {
|
||||
"parents": [],
|
||||
"children": []
|
||||
},
|
||||
"documents": [
|
||||
{
|
||||
"id": "doc_quantum_paper",
|
||||
"title": "Quantum Computing Applications",
|
||||
"type": "pdf",
|
||||
"createdAt": "2024-01-10T08:00:00Z",
|
||||
"updatedAt": "2024-01-10T08:00:00Z"
|
||||
}
|
||||
]
|
||||
},
|
||||
{
|
||||
"id": "chunk_abc123",
|
||||
"chunk": "This is a chunk of content from a document about quantum computing...",
|
||||
"similarity": 0.82,
|
||||
"metadata": {
|
||||
"category": "research",
|
||||
"source": "document"
|
||||
},
|
||||
"updatedAt": "2024-01-15T10:30:00Z",
|
||||
"version": 1,
|
||||
"context": {
|
||||
"parents": [],
|
||||
"children": []
|
||||
},
|
||||
"documents": [
|
||||
{
|
||||
"id": "doc_quantum_research",
|
||||
"title": "Quantum Computing Research Paper",
|
||||
"type": "pdf",
|
||||
"metadata": {
|
||||
"author": "Dr. Smith"
|
||||
},
|
||||
"createdAt": "2024-01-15T10:30:00Z",
|
||||
"updatedAt": "2024-01-15T10:30:00Z"
|
||||
}
|
||||
]
|
||||
}
|
||||
],
|
||||
"timing": 198,
|
||||
"total": 2
|
||||
}
|
||||
```
|
||||
|
||||
<Note>
|
||||
**Distinguishing Memory vs Chunk Results:**
|
||||
|
||||
In hybrid mode, check which key exists on the result object:
|
||||
- **Memory results**: Have a `memory` key (no `chunk` key)
|
||||
- **Chunk results**: Have a `chunk` key (no `memory` key)
|
||||
|
||||
```typescript
|
||||
// TypeScript example
|
||||
results.results.forEach(result => {
|
||||
if ('memory' in result) {
|
||||
// This is a memory result
|
||||
console.log('Memory:', result.memory);
|
||||
} else if ('chunk' in result) {
|
||||
// This is a chunk result
|
||||
console.log('Chunk:', result.chunk);
|
||||
}
|
||||
});
|
||||
```
|
||||
</Note>
|
||||
|
||||
### Memory Result Fields
|
||||
|
||||
<ResponseField name="id" type="string">
|
||||
Unique identifier for the memory entry or chunk ID. In hybrid mode, can be either a memory ID (e.g., `mem_xyz789`) or a chunk ID (e.g., `chunk_abc123`).
|
||||
</ResponseField>
|
||||
|
||||
<ResponseField name="memory" type="string" optional>
|
||||
**Complete memory content**. Only present for memory results (when `searchMode="memories"` or when a memory result is returned in hybrid mode). This field is not present for chunk results.
|
||||
</ResponseField>
|
||||
|
||||
<ResponseField name="chunk" type="string" optional>
|
||||
**Chunk content from a document**. Only present for chunk results when `searchMode="hybrid"`. This field is not present for memory results. Contains the actual text content from the document chunk.
|
||||
</ResponseField>
|
||||
|
||||
<ResponseField name="similarity" type="number" range="0-1">
|
||||
**Similarity score** between your query and this memory. Higher scores indicate better matches.
|
||||
|
||||
- **0.9-1.0**: Extremely similar
|
||||
- **0.8-0.9**: Very similar
|
||||
- **0.7-0.8**: Similar
|
||||
- **0.6-0.7**: Somewhat similar
|
||||
- **0.5-0.6**: Marginally similar
|
||||
</ResponseField>
|
||||
|
||||
<ResponseField name="metadata" type="object | null">
|
||||
Memory metadata as key-value pairs. Structure depends on what was stored with the memory.
|
||||
</ResponseField>
|
||||
|
||||
<ResponseField name="updatedAt" type="string">
|
||||
ISO 8601 timestamp when the memory was last updated.
|
||||
</ResponseField>
|
||||
|
||||
<ResponseField name="version" type="number | null" optional>
|
||||
Version number of this memory entry. Used for tracking memory evolution and relationships. For chunk results, this is typically `1`.
|
||||
</ResponseField>
|
||||
|
||||
<ResponseField name="rootMemoryId" type="string | null" optional>
|
||||
Root memory ID for memory entries. Only present for memory results. Always `null` for chunk results.
|
||||
</ResponseField>
|
||||
|
||||
<ResponseField name="context" type="object" optional>
|
||||
**Contextual memory relationships**. Only included when `include.relatedMemories=true`.
|
||||
|
||||
<ResponseField name="context.parents" type="Array<ContextMemory>" optional>
|
||||
Array of parent memories that this memory extends or derives from.
|
||||
</ResponseField>
|
||||
|
||||
<ResponseField name="context.children" type="Array<ContextMemory>" optional>
|
||||
Array of child memories that extend or derive from this memory.
|
||||
</ResponseField>
|
||||
|
||||
### Context Memory Structure
|
||||
|
||||
<ResponseField name="memory" type="string">
|
||||
Content of the related memory.
|
||||
</ResponseField>
|
||||
|
||||
<ResponseField name="relation" type="string">
|
||||
Relationship type: `"updates"`, `"extends"`, or `"derives"`.
|
||||
|
||||
- **updates**: This memory updates/replaces the related memory
|
||||
- **extends**: This memory builds upon the related memory
|
||||
- **derives**: This memory is derived from the related memory
|
||||
</ResponseField>
|
||||
|
||||
<ResponseField name="version" type="number | null">
|
||||
Relative version distance:
|
||||
- **Negative values** for parents (-1 = direct parent, -2 = grandparent)
|
||||
- **Positive values** for children (+1 = direct child, +2 = grandchild)
|
||||
</ResponseField>
|
||||
|
||||
<ResponseField name="updatedAt" type="string">
|
||||
When the related memory was last updated.
|
||||
</ResponseField>
|
||||
|
||||
<ResponseField name="metadata" type="object | null" optional>
|
||||
Metadata of the related memory.
|
||||
</ResponseField>
|
||||
</ResponseField>
|
||||
|
||||
<ResponseField name="documents" type="Array<Document>" optional>
|
||||
**Associated documents**. Only included when `include.documents=true`.
|
||||
|
||||
<ResponseField name="documents[].id" type="string">
|
||||
Document identifier.
|
||||
</ResponseField>
|
||||
|
||||
<ResponseField name="documents[].title" type="string">
|
||||
Document title.
|
||||
</ResponseField>
|
||||
|
||||
<ResponseField name="documents[].type" type="string">
|
||||
Document type.
|
||||
</ResponseField>
|
||||
|
||||
<ResponseField name="documents[].metadata" type="object">
|
||||
Document metadata.
|
||||
</ResponseField>
|
||||
|
||||
<ResponseField name="documents[].createdAt" type="string">
|
||||
Document creation timestamp.
|
||||
</ResponseField>
|
||||
|
||||
<ResponseField name="documents[].updatedAt" type="string">
|
||||
Document update timestamp.
|
||||
</ResponseField>
|
||||
</ResponseField>
|
||||
|
|
@ -1,523 +0,0 @@
|
|||
---
|
||||
title: "Update & Delete Memories"
|
||||
description: "Safely update and delete memories with upsert patterns and idempotency"
|
||||
icon: "delete"
|
||||
---
|
||||
|
||||
Choose from direct updates, idempotent upserts, single deletions, and powerful bulk operations.
|
||||
|
||||
## Direct Updates
|
||||
|
||||
Update existing memories by their ID when you know the specific memory you want to modify.
|
||||
|
||||
- **Content changes** — Trigger full reprocessing (reindexing) through the pipeline. Response status is `"queued"`.
|
||||
- **Metadata-only changes** — Update the document row only; no reindexing. Response status stays `"done"`. Use this when updating fields like `accepted`, `version`, or other filter metadata without changing the document content.
|
||||
|
||||
<CodeGroup>
|
||||
|
||||
```typescript Typescript
|
||||
import Supermemory from 'supermemory';
|
||||
|
||||
const client = new Supermemory({
|
||||
apiKey: process.env.SUPERMEMORY_API_KEY!
|
||||
});
|
||||
|
||||
// Update by memory ID
|
||||
const updated = await client.documents.update('memory_id_123', {
|
||||
content: 'Updated content here',
|
||||
metadata: { version: 2, updated: true }
|
||||
});
|
||||
|
||||
console.log(updated.status); // "queued" when content changed; "done" when metadata-only
|
||||
console.log(updated.id); // "memory_id_123"
|
||||
```
|
||||
|
||||
```python Python
|
||||
from supermemory import Supermemory
|
||||
import os
|
||||
|
||||
client = Supermemory(api_key=os.environ.get("SUPERMEMORY_API_KEY"))
|
||||
|
||||
# Update by memory ID
|
||||
updated = client.documents.update(
|
||||
'memory_id_123',
|
||||
content='Updated content here',
|
||||
metadata={'version': 2, 'updated': True}
|
||||
)
|
||||
|
||||
print(f"Status: {updated.status}") # "queued" when content changed; "done" when metadata-only
|
||||
print(f"ID: {updated.id}") # "memory_id_123"
|
||||
```
|
||||
|
||||
```bash cURL
|
||||
curl -X PATCH "https://api.supermemory.ai/v3/documents/memory_id_123" \
|
||||
-H "Authorization: Bearer $SUPERMEMORY_API_KEY" \
|
||||
-H "Content-Type: application/json" \
|
||||
-d '{
|
||||
"content": "Updated content here",
|
||||
"metadata": {"version": 2, "updated": true}
|
||||
}'
|
||||
```
|
||||
|
||||
</CodeGroup>
|
||||
|
||||
<Note>
|
||||
**Metadata-only updates:** If you omit `content` or send the same content and only change `metadata` (e.g. `accepted: false` → `accepted: true`), the document is updated in place with no reindexing. Works with both internal `id` and `customId`—no special setup required.
|
||||
</Note>
|
||||
|
||||
## Upserts Using customId
|
||||
|
||||
Use `customId` for idempotent operations where the same `customId` with `add()` will update existing memory instead of creating duplicates.
|
||||
|
||||
<CodeGroup>
|
||||
|
||||
```typescript Typescript
|
||||
import Supermemory from 'supermemory';
|
||||
|
||||
const client = new Supermemory({
|
||||
apiKey: process.env.SUPERMEMORY_API_KEY!
|
||||
});
|
||||
|
||||
const customId = 'user-note-001';
|
||||
|
||||
// First call creates memory
|
||||
const created = await client.add({
|
||||
content: 'Initial content',
|
||||
customId: customId,
|
||||
metadata: { version: 1 }
|
||||
});
|
||||
|
||||
console.log('Created memory:', created.id);
|
||||
|
||||
// Second call with same customId updates existing
|
||||
const updated = await client.add({
|
||||
content: 'Updated content',
|
||||
customId: customId, // Same customId = upsert
|
||||
metadata: { version: 2 }
|
||||
});
|
||||
```
|
||||
|
||||
```python Python
|
||||
from supermemory import Supermemory
|
||||
import os
|
||||
|
||||
client = Supermemory(api_key=os.environ.get("SUPERMEMORY_API_KEY"))
|
||||
|
||||
custom_id = 'user-note-001'
|
||||
|
||||
# First call creates memory
|
||||
created = client.add(
|
||||
content='Initial content',
|
||||
custom_id=custom_id,
|
||||
metadata={'version': 1}
|
||||
)
|
||||
|
||||
print(f'Created memory: {created.id}')
|
||||
|
||||
# Second call with same customId updates existing
|
||||
updated = client.add(
|
||||
content='Updated content',
|
||||
custom_id=custom_id, # Same customId = upsert
|
||||
metadata={'version': 2}
|
||||
)
|
||||
|
||||
print(f'Updated memory: {updated.id}')
|
||||
print(f'Same memory? {created.id == updated.id}') # True
|
||||
```
|
||||
|
||||
```bash cURL
|
||||
# First call - creates memory
|
||||
curl -X POST "https://api.supermemory.ai/v3/documents" \
|
||||
-H "Authorization: Bearer $SUPERMEMORY_API_KEY" \
|
||||
-H "Content-Type: application/json" \
|
||||
-d '{
|
||||
"content": "Initial content",
|
||||
"customId": "user-note-001",
|
||||
"metadata": {"version": 1}
|
||||
}'
|
||||
|
||||
# Response: {"id": "mem_abc123", "status": "queued", "customId": "user-note-001"}
|
||||
|
||||
# Second call - updates existing (same customId)
|
||||
curl -X POST "https://api.supermemory.ai/v3/documents" \
|
||||
-H "Authorization: Bearer $SUPERMEMORY_API_KEY" \
|
||||
-H "Content-Type: application/json" \
|
||||
-d '{
|
||||
"content": "Updated content",
|
||||
"customId": "user-note-001",
|
||||
"metadata": {"version": 2}
|
||||
}'
|
||||
|
||||
# Response: {"id": "mem_abc123", "status": "queued", "customId": "user-note-001"}
|
||||
# Note: Same ID returned - memory was updated, not created
|
||||
```
|
||||
|
||||
</CodeGroup>
|
||||
|
||||
<Note>
|
||||
The `customId` enables idempotency across all endpoints. The `memoryId` doesn't support idempotency, only the `customId` does.
|
||||
</Note>
|
||||
|
||||
<Warning>
|
||||
|
||||
The `customId` can have a maximum length of 100 characters.
|
||||
|
||||
</Warning>
|
||||
|
||||
## Single Delete
|
||||
|
||||
Delete individual memories by their ID. This is a permanent hard delete with no recovery mechanism.
|
||||
|
||||
<CodeGroup>
|
||||
|
||||
```typescript Typescript
|
||||
// Hard delete - permanently removes memory
|
||||
await client.documents.delete('memory_id_123');
|
||||
console.log('Memory deleted successfully');
|
||||
```
|
||||
|
||||
```python Python
|
||||
# Hard delete - permanently removes memory
|
||||
client.documents.delete('memory_id_123')
|
||||
print('Memory deleted successfully')
|
||||
|
||||
# Error handling for single delete
|
||||
try:
|
||||
client.documents.delete('memory_id_123')
|
||||
print('Delete successful')
|
||||
except NotFoundError:
|
||||
print('Memory not found or already deleted')
|
||||
except AuthenticationError:
|
||||
print('Authentication failed')
|
||||
except Exception as e:
|
||||
print(f'Delete failed: {e}')
|
||||
```
|
||||
|
||||
```bash cURL
|
||||
curl -X DELETE "https://api.supermemory.ai/v3/documents/memory_id_123" \
|
||||
-H "Authorization: Bearer $SUPERMEMORY_API_KEY"
|
||||
|
||||
# Response: 204 No Content (success)
|
||||
# Response: 404 Not Found (memory doesn't exist)
|
||||
```
|
||||
|
||||
</CodeGroup>
|
||||
|
||||
## Bulk Delete by IDs
|
||||
|
||||
Delete multiple memories at once by providing an array of memory IDs. Maximum of 100 IDs per request.
|
||||
|
||||
<CodeGroup>
|
||||
|
||||
```typescript Typescript
|
||||
// Bulk delete by memory IDs
|
||||
const result = await client.documents.deleteBulk({
|
||||
ids: [
|
||||
'memory_id_1',
|
||||
'memory_id_2',
|
||||
'memory_id_3',
|
||||
'non_existent_id' // This will be reported in errors
|
||||
]
|
||||
});
|
||||
|
||||
console.log('Bulk delete result:', result);
|
||||
// Output: {
|
||||
// success: true,
|
||||
// deletedCount: 3,
|
||||
// errors: [
|
||||
// { id: "non_existent_id", error: "Memory not found" }
|
||||
// ]
|
||||
// }
|
||||
```
|
||||
|
||||
```python Python
|
||||
# Bulk delete by memory IDs
|
||||
result = client.documents.delete_bulk(
|
||||
ids=[
|
||||
'memory_id_1',
|
||||
'memory_id_2',
|
||||
'memory_id_3',
|
||||
'non_existent_id' # This will be reported in errors
|
||||
]
|
||||
)
|
||||
|
||||
print(f'Bulk delete result: {result}')
|
||||
# Output: {
|
||||
# 'success': True,
|
||||
# 'deletedCount': 3,
|
||||
# 'errors': [
|
||||
# {'id': 'non_existent_id', 'error': 'Memory not found'}
|
||||
# ]
|
||||
# }
|
||||
```
|
||||
|
||||
```bash cURL
|
||||
curl -X DELETE "https://api.supermemory.ai/v3/documents/bulk" \
|
||||
-H "Authorization: Bearer $SUPERMEMORY_API_KEY" \
|
||||
-H "Content-Type: application/json" \
|
||||
-d '{
|
||||
"ids": [
|
||||
"memory_id_1",
|
||||
"memory_id_2",
|
||||
"memory_id_3",
|
||||
"non_existent_id"
|
||||
]
|
||||
}'
|
||||
|
||||
# Response: {
|
||||
# "success": true,
|
||||
# "deletedCount": 3,
|
||||
# "errors": [
|
||||
# {"id": "non_existent_id", "error": "Memory not found"}
|
||||
# ]
|
||||
# }
|
||||
```
|
||||
|
||||
</CodeGroup>
|
||||
|
||||
## Bulk Delete by Container Tags
|
||||
|
||||
Delete all memories within specific container tags. This is useful for cleaning up entire projects or user data.
|
||||
|
||||
<CodeGroup>
|
||||
|
||||
```typescript Typescript
|
||||
// Delete all memories in specific container tags
|
||||
const result = await client.documents.deleteBulk({
|
||||
containerTags: ['user-123', 'project-old', 'archived-content']
|
||||
});
|
||||
|
||||
console.log('Bulk delete by tags result:', result);
|
||||
// Output: {
|
||||
// success: true,
|
||||
// deletedCount: 45,
|
||||
// containerTags: ["user-123", "project-old", "archived-content"]
|
||||
// }
|
||||
```
|
||||
|
||||
```python Python
|
||||
# Delete all memories in specific container tags
|
||||
result = client.documents.delete_bulk(
|
||||
container_tags=['user-123', 'project-old', 'archived-content']
|
||||
)
|
||||
|
||||
print(f'Bulk delete by tags result: {result}')
|
||||
# Output: {
|
||||
# 'success': True,
|
||||
# 'deletedCount': 45,
|
||||
# 'containerTags': ['user-123', 'project-old', 'archived-content']
|
||||
# }
|
||||
```
|
||||
|
||||
```bash cURL
|
||||
curl -X DELETE "https://api.supermemory.ai/v3/documents/bulk" \
|
||||
-H "Authorization: Bearer $SUPERMEMORY_API_KEY" \
|
||||
-H "Content-Type: application/json" \
|
||||
-d '{
|
||||
"containerTags": ["user-123", "project-old", "archived-content"]
|
||||
}'
|
||||
|
||||
# Response: {
|
||||
# "success": true,
|
||||
# "deletedCount": 45,
|
||||
# "containerTags": ["user-123", "project-old", "archived-content"]
|
||||
# }
|
||||
```
|
||||
|
||||
</CodeGroup>
|
||||
|
||||
## Advanced Patterns
|
||||
|
||||
### Soft Delete Implementation
|
||||
|
||||
For applications requiring audit trails or recovery mechanisms, implement soft delete patterns using metadata:
|
||||
|
||||
<CodeGroup>
|
||||
|
||||
```typescript Typescript
|
||||
// Soft delete pattern using metadata
|
||||
await client.documents.update('memory_id', {
|
||||
metadata: {
|
||||
deleted: true,
|
||||
deletedAt: new Date().toISOString(),
|
||||
deletedBy: 'user_123'
|
||||
}
|
||||
});
|
||||
|
||||
// Filter out deleted memories in searches
|
||||
const activeMemories = await client.documents.list({
|
||||
filters: {
|
||||
AND: [
|
||||
{ key: "deleted", value: "true", negate: true }
|
||||
]
|
||||
}
|
||||
});
|
||||
|
||||
console.log('Active memories:', activeMemories.memories.length);
|
||||
```
|
||||
|
||||
```python Python
|
||||
from datetime import datetime
|
||||
|
||||
# Soft delete pattern using metadata
|
||||
client.documents.update(
|
||||
'memory_id',
|
||||
metadata={
|
||||
'deleted': True,
|
||||
'deletedAt': datetime.now().isoformat(),
|
||||
'deletedBy': 'user_123'
|
||||
}
|
||||
)
|
||||
|
||||
# Filter out deleted memories
|
||||
active_memories = client.documents.list(
|
||||
filters={
|
||||
"AND": [
|
||||
{"key": "deleted", "value": "true", "negate": True}
|
||||
]
|
||||
}
|
||||
)
|
||||
|
||||
print(f'Active memories: {len(active_memories.memories)}')
|
||||
```
|
||||
|
||||
```bash cURL
|
||||
# Soft delete using metadata
|
||||
curl -X PATCH "https://api.supermemory.ai/v3/documents/memory_id" \
|
||||
-H "Authorization: Bearer $SUPERMEMORY_API_KEY" \
|
||||
-H "Content-Type: application/json" \
|
||||
-d '{
|
||||
"metadata": {
|
||||
"deleted": true,
|
||||
"deletedAt": "2024-01-15T10:30:00Z",
|
||||
"deletedBy": "user_123"
|
||||
}
|
||||
}'
|
||||
|
||||
# Response: {"id": "memory_id", "status": "queued"}
|
||||
```
|
||||
|
||||
</CodeGroup>
|
||||
|
||||
### Batch Processing for Large Operations
|
||||
|
||||
<CodeGroup>
|
||||
|
||||
```typescript Typescript
|
||||
// Batch delete large numbers of memories safely
|
||||
async function batchDeleteMemories(memoryIds: string[], batchSize = 100) {
|
||||
const results = [];
|
||||
|
||||
for (let i = 0; i < memoryIds.length; i += batchSize) {
|
||||
const batch = memoryIds.slice(i, i + batchSize);
|
||||
|
||||
console.log(`Processing batch ${Math.floor(i/batchSize) + 1} of ${Math.ceil(memoryIds.length/batchSize)}`);
|
||||
|
||||
try {
|
||||
const result = await client.documents.deleteBulk({ ids: batch });
|
||||
results.push(result);
|
||||
|
||||
// Brief delay between batches to avoid rate limiting
|
||||
if (i + batchSize < memoryIds.length) {
|
||||
await new Promise(resolve => setTimeout(resolve, 1000));
|
||||
}
|
||||
} catch (error) {
|
||||
console.error(`Batch ${Math.floor(i/batchSize) + 1} failed:`, error);
|
||||
results.push({ success: false, error: error.message, batch });
|
||||
}
|
||||
}
|
||||
|
||||
// Aggregate results
|
||||
const totalDeleted = results
|
||||
.filter(r => r.success)
|
||||
.reduce((sum, r) => sum + (r.deletedCount || 0), 0);
|
||||
|
||||
console.log(`Total deleted: ${totalDeleted} out of ${memoryIds.length}`);
|
||||
return { totalDeleted, results };
|
||||
}
|
||||
```
|
||||
|
||||
```python Python
|
||||
import time
|
||||
import math
|
||||
|
||||
def batch_delete_memories(memory_ids, batch_size=100):
|
||||
"""Batch delete large numbers of memories safely"""
|
||||
results = []
|
||||
|
||||
for i in range(0, len(memory_ids), batch_size):
|
||||
batch = memory_ids[i:i + batch_size]
|
||||
batch_num = i // batch_size + 1
|
||||
total_batches = math.ceil(len(memory_ids) / batch_size)
|
||||
|
||||
print(f'Processing batch {batch_num} of {total_batches}')
|
||||
|
||||
try:
|
||||
result = client.documents.delete_bulk(ids=batch)
|
||||
results.append(result)
|
||||
|
||||
# Brief delay between batches to avoid rate limiting
|
||||
if i + batch_size < len(memory_ids):
|
||||
time.sleep(1)
|
||||
except Exception as error:
|
||||
print(f'Batch {batch_num} failed: {error}')
|
||||
results.append({'success': False, 'error': str(error), 'batch': batch})
|
||||
|
||||
# Aggregate results
|
||||
total_deleted = sum(
|
||||
r.get('deletedCount', 0) for r in results if r.get('success')
|
||||
)
|
||||
|
||||
print(f'Total deleted: {total_deleted} out of {len(memory_ids)}')
|
||||
return {'totalDeleted': total_deleted, 'results': results}
|
||||
```
|
||||
|
||||
```bash cURL
|
||||
# Batch processing script example
|
||||
#!/bin/bash
|
||||
|
||||
MEMORY_IDS=("id1" "id2" "id3") # Your memory IDs array
|
||||
BATCH_SIZE=100
|
||||
TOTAL_DELETED=0
|
||||
|
||||
# Process in batches
|
||||
for ((i=0; i<${#MEMORY_IDS[@]}; i+=BATCH_SIZE)); do
|
||||
batch=("${MEMORY_IDS[@]:i:BATCH_SIZE}")
|
||||
batch_json=$(printf '%s\n' "${batch[@]}" | jq -R . | jq -s .)
|
||||
|
||||
echo "Processing batch $((i/BATCH_SIZE + 1))"
|
||||
|
||||
response=$(curl -s -X DELETE \
|
||||
"https://api.supermemory.ai/v3/documents/bulk" \
|
||||
-H "Authorization: Bearer $SUPERMEMORY_API_KEY" \
|
||||
-H "Content-Type: application/json" \
|
||||
-d "{\"ids\": $batch_json}")
|
||||
|
||||
deleted_count=$(echo "$response" | jq -r '.deletedCount // 0')
|
||||
TOTAL_DELETED=$((TOTAL_DELETED + deleted_count))
|
||||
|
||||
echo "Batch deleted: $deleted_count memories"
|
||||
sleep 1 # Rate limiting protection
|
||||
done
|
||||
|
||||
echo "Total deleted: $TOTAL_DELETED memories"
|
||||
```
|
||||
|
||||
</CodeGroup>
|
||||
|
||||
## Best Practices
|
||||
|
||||
### Update Operations
|
||||
|
||||
1. **Use customId for idempotent updates** - Prevents duplicate memories and enables safe retries
|
||||
2. **Monitor processing status** - Content changes trigger full reprocessing; metadata-only updates do not reindex
|
||||
3. **Handle metadata carefully** - Updates replace specified metadata keys
|
||||
4. **Implement proper error handling** - Memory may be deleted between operations
|
||||
|
||||
### Delete Operations
|
||||
|
||||
1. **Hard delete is permanent** - No recovery mechanism exists
|
||||
2. **Use bulk operations efficiently** - Maximum 100 IDs per bulk delete request
|
||||
3. **Consider soft delete patterns** - Use metadata flags for recoverable deletion
|
||||
4. **Batch large operations** - Avoid rate limits with proper batching
|
||||
5. **Clean up application state** - Update your UI/cache after deletions
|
||||
|
|
@ -367,7 +367,7 @@ a vague one. `static` and `dynamic` are reserved and can't be used as bucket key
|
|||
import { openai } from "@ai-sdk/openai"
|
||||
|
||||
// Profiles automatically injected
|
||||
const model = withSupermemory(openai("gpt-4"), {
|
||||
const model = withSupermemory(openai("gpt-4o"), {
|
||||
containerTag: "user-123",
|
||||
customId: "conv-1",
|
||||
})
|
||||
|
|
|
|||
|
|
@ -1,226 +0,0 @@
|
|||
---
|
||||
title: "Profile API"
|
||||
description: "Endpoint details and response structure for user profiles"
|
||||
sidebarTitle: "API Reference"
|
||||
icon: "code"
|
||||
---
|
||||
|
||||
## Endpoint
|
||||
|
||||
**`POST /v4/profile`**
|
||||
|
||||
Retrieves a user's profile, optionally combined with search results.
|
||||
|
||||
## Request
|
||||
|
||||
### Headers
|
||||
|
||||
| Header | Required | Description |
|
||||
|--------|----------|-------------|
|
||||
| `Authorization` | Yes | Bearer token with your API key |
|
||||
| `Content-Type` | Yes | `application/json` |
|
||||
|
||||
### Body Parameters
|
||||
|
||||
| Parameter | Type | Required | Description |
|
||||
|-----------|------|----------|-------------|
|
||||
| `containerTag` | string | Yes | The container tag (usually user ID) to get profiles for |
|
||||
| `threshold` | float | No | Threshold for filtering search results. Only results with a score above this threshold will be included. |
|
||||
| `q` | string | No | Optional search query to include search results with the profile |
|
||||
|
||||
## Response
|
||||
|
||||
```json
|
||||
{
|
||||
"profile": {
|
||||
"static": [
|
||||
"User is a software engineer",
|
||||
"User specializes in Python and React",
|
||||
"User prefers dark mode interfaces"
|
||||
],
|
||||
"dynamic": [
|
||||
"User is working on Project Alpha",
|
||||
"User recently started learning Rust",
|
||||
"User is debugging authentication issues"
|
||||
]
|
||||
},
|
||||
"searchResults": {
|
||||
"results": [...], // Only if 'q' parameter was provided
|
||||
"total": 15,
|
||||
"timing": 45.2
|
||||
}
|
||||
}
|
||||
```
|
||||
|
||||
### Response Fields
|
||||
|
||||
| Field | Type | Description |
|
||||
|-------|------|-------------|
|
||||
| `profile.static` | string[] | Long-term, stable facts about the user |
|
||||
| `profile.dynamic` | string[] | Recent context and temporary information |
|
||||
| `searchResults` | object | Only present if `q` parameter was provided |
|
||||
| `searchResults.results` | array | Matching memory results |
|
||||
| `searchResults.total` | number | Total number of matches |
|
||||
| `searchResults.timing` | number | Query execution time in milliseconds |
|
||||
|
||||
## Basic Request
|
||||
|
||||
<CodeGroup>
|
||||
|
||||
```typescript TypeScript
|
||||
const response = await fetch('https://api.supermemory.ai/v4/profile', {
|
||||
method: 'POST',
|
||||
headers: {
|
||||
'Authorization': `Bearer ${process.env.SUPERMEMORY_API_KEY}`,
|
||||
'Content-Type': 'application/json'
|
||||
},
|
||||
body: JSON.stringify({
|
||||
containerTag: 'user_123'
|
||||
})
|
||||
});
|
||||
|
||||
const data = await response.json();
|
||||
|
||||
console.log("Static facts:", data.profile.static);
|
||||
console.log("Dynamic context:", data.profile.dynamic);
|
||||
```
|
||||
|
||||
```python Python
|
||||
import requests
|
||||
import os
|
||||
|
||||
response = requests.post(
|
||||
'https://api.supermemory.ai/v4/profile',
|
||||
headers={
|
||||
'Authorization': f'Bearer {os.getenv("SUPERMEMORY_API_KEY")}',
|
||||
'Content-Type': 'application/json'
|
||||
},
|
||||
json={
|
||||
'containerTag': 'user_123'
|
||||
}
|
||||
)
|
||||
|
||||
data = response.json()
|
||||
|
||||
print("Static facts:", data['profile']['static'])
|
||||
print("Dynamic context:", data['profile']['dynamic'])
|
||||
```
|
||||
|
||||
```bash cURL
|
||||
curl -X POST https://api.supermemory.ai/v4/profile \
|
||||
-H "Authorization: Bearer YOUR_API_KEY" \
|
||||
-H "Content-Type: application/json" \
|
||||
-d '{
|
||||
"containerTag": "user_123"
|
||||
}'
|
||||
```
|
||||
|
||||
</CodeGroup>
|
||||
|
||||
## Profile with Search
|
||||
|
||||
Include a search query to get both profile data and relevant memories in one call:
|
||||
|
||||
<CodeGroup>
|
||||
|
||||
```typescript TypeScript
|
||||
const response = await fetch('https://api.supermemory.ai/v4/profile', {
|
||||
method: 'POST',
|
||||
headers: {
|
||||
'Authorization': `Bearer ${process.env.SUPERMEMORY_API_KEY}`,
|
||||
'Content-Type': 'application/json'
|
||||
},
|
||||
body: JSON.stringify({
|
||||
containerTag: 'user_123',
|
||||
q: 'deployment errors yesterday'
|
||||
})
|
||||
});
|
||||
|
||||
const data = await response.json();
|
||||
|
||||
// Profile data
|
||||
const profile = data.profile;
|
||||
|
||||
// Search results (only present because we passed 'q')
|
||||
const searchResults = data.searchResults?.results || [];
|
||||
```
|
||||
|
||||
```python Python
|
||||
response = requests.post(
|
||||
'https://api.supermemory.ai/v4/profile',
|
||||
headers={
|
||||
'Authorization': f'Bearer {os.getenv("SUPERMEMORY_API_KEY")}',
|
||||
'Content-Type': 'application/json'
|
||||
},
|
||||
json={
|
||||
'containerTag': 'user_123',
|
||||
'q': 'deployment errors yesterday'
|
||||
}
|
||||
)
|
||||
|
||||
data = response.json()
|
||||
|
||||
profile = data['profile']
|
||||
search_results = data.get('searchResults', {}).get('results', [])
|
||||
```
|
||||
|
||||
</CodeGroup>
|
||||
|
||||
## Profile with Threshold
|
||||
|
||||
Use the optional `threshold` parameter to filter search results by relevance score:
|
||||
|
||||
<CodeGroup>
|
||||
|
||||
```typescript TypeScript
|
||||
const response = await fetch('https://api.supermemory.ai/v4/profile', {
|
||||
method: 'POST',
|
||||
headers: {
|
||||
'Authorization': `Bearer ${process.env.SUPERMEMORY_API_KEY}`,
|
||||
'Content-Type': 'application/json'
|
||||
},
|
||||
body: JSON.stringify({
|
||||
containerTag: 'user_123',
|
||||
threshold: 0.7, // Only include results with score > 0.7
|
||||
q: 'deployment errors yesterday'
|
||||
})
|
||||
});
|
||||
|
||||
const data = await response.json();
|
||||
```
|
||||
|
||||
```python Python
|
||||
response = requests.post(
|
||||
'https://api.supermemory.ai/v4/profile',
|
||||
headers={
|
||||
'Authorization': f'Bearer {os.getenv("SUPERMEMORY_API_KEY")}',
|
||||
'Content-Type': 'application/json'
|
||||
},
|
||||
json={
|
||||
'containerTag': 'user_123',
|
||||
'threshold': 0.7, # Only include results with score > 0.7
|
||||
'q': 'deployment errors yesterday'
|
||||
}
|
||||
)
|
||||
|
||||
data = response.json()
|
||||
```
|
||||
|
||||
</CodeGroup>
|
||||
|
||||
## Error Responses
|
||||
|
||||
| Status | Description |
|
||||
|--------|-------------|
|
||||
| `400` | Missing or invalid `containerTag` or `threshold` |
|
||||
| `401` | Invalid or missing API key |
|
||||
| `404` | Container not found |
|
||||
| `500` | Internal server error |
|
||||
|
||||
## Rate Limits
|
||||
|
||||
Profile requests count toward your standard API rate limits. Since profiles are cached, repeated requests for the same user are efficient.
|
||||
|
||||
<Card title="See Examples" icon="laptop-code" href="/user-profiles/examples">
|
||||
View complete integration examples for chat apps, support systems, and more
|
||||
</Card>
|
||||
|
|
@ -1,370 +0,0 @@
|
|||
---
|
||||
title: "Profile Examples"
|
||||
description: "Complete code examples for integrating user profiles"
|
||||
sidebarTitle: "Examples"
|
||||
icon: "laptop-code"
|
||||
---
|
||||
|
||||
## Building a Personalized Prompt
|
||||
|
||||
The most common use case: inject profile data into your LLM's system prompt.
|
||||
|
||||
<CodeGroup>
|
||||
|
||||
```typescript TypeScript
|
||||
async function handleChatMessage(userId: string, message: string) {
|
||||
// Get user profile
|
||||
const profileResponse = await fetch('https://api.supermemory.ai/v4/profile', {
|
||||
method: 'POST',
|
||||
headers: {
|
||||
'Authorization': `Bearer ${process.env.SUPERMEMORY_API_KEY}`,
|
||||
'Content-Type': 'application/json'
|
||||
},
|
||||
body: JSON.stringify({ containerTag: userId })
|
||||
});
|
||||
|
||||
const { profile } = await profileResponse.json();
|
||||
|
||||
// Build personalized system prompt
|
||||
const systemPrompt = `You are assisting a user with the following context:
|
||||
|
||||
ABOUT THE USER:
|
||||
${profile.static?.join('\n') || 'No profile information yet.'}
|
||||
|
||||
CURRENT CONTEXT:
|
||||
${profile.dynamic?.join('\n') || 'No recent activity.'}
|
||||
|
||||
Provide responses personalized to their expertise level and preferences.`;
|
||||
|
||||
// Send to your LLM
|
||||
const response = await llm.chat({
|
||||
messages: [
|
||||
{ role: "system", content: systemPrompt },
|
||||
{ role: "user", content: message }
|
||||
]
|
||||
});
|
||||
|
||||
return response;
|
||||
}
|
||||
```
|
||||
|
||||
```python Python
|
||||
import requests
|
||||
import os
|
||||
|
||||
async def handle_chat_message(user_id: str, message: str):
|
||||
# Get user profile
|
||||
response = requests.post(
|
||||
'https://api.supermemory.ai/v4/profile',
|
||||
headers={
|
||||
'Authorization': f'Bearer {os.getenv("SUPERMEMORY_API_KEY")}',
|
||||
'Content-Type': 'application/json'
|
||||
},
|
||||
json={'containerTag': user_id}
|
||||
)
|
||||
|
||||
profile = response.json()['profile']
|
||||
|
||||
# Build personalized system prompt
|
||||
static_facts = '\n'.join(profile.get('static', ['No profile information yet.']))
|
||||
dynamic_context = '\n'.join(profile.get('dynamic', ['No recent activity.']))
|
||||
|
||||
system_prompt = f"""You are assisting a user with the following context:
|
||||
|
||||
ABOUT THE USER:
|
||||
{static_facts}
|
||||
|
||||
CURRENT CONTEXT:
|
||||
{dynamic_context}
|
||||
|
||||
Provide responses personalized to their expertise level and preferences."""
|
||||
|
||||
# Send to your LLM
|
||||
llm_response = await llm.chat(
|
||||
messages=[
|
||||
{"role": "system", "content": system_prompt},
|
||||
{"role": "user", "content": message}
|
||||
]
|
||||
)
|
||||
|
||||
return llm_response
|
||||
```
|
||||
|
||||
</CodeGroup>
|
||||
|
||||
## Full Context Mode
|
||||
|
||||
Combine profile data with query-specific search for comprehensive context:
|
||||
|
||||
<CodeGroup>
|
||||
|
||||
```typescript TypeScript
|
||||
async function getFullContext(userId: string, userQuery: string) {
|
||||
// Single call gets both profile and search results
|
||||
const response = await fetch('https://api.supermemory.ai/v4/profile', {
|
||||
method: 'POST',
|
||||
headers: {
|
||||
'Authorization': `Bearer ${process.env.SUPERMEMORY_API_KEY}`,
|
||||
'Content-Type': 'application/json'
|
||||
},
|
||||
body: JSON.stringify({
|
||||
containerTag: userId,
|
||||
q: userQuery // Include the user's query
|
||||
})
|
||||
});
|
||||
|
||||
const data = await response.json();
|
||||
|
||||
return {
|
||||
// Static background about the user
|
||||
userBackground: data.profile.static,
|
||||
// Current activities and context
|
||||
currentContext: data.profile.dynamic,
|
||||
// Query-specific memories
|
||||
relevantMemories: data.searchResults?.results || []
|
||||
};
|
||||
}
|
||||
|
||||
// Usage
|
||||
const context = await getFullContext('user_123', 'deployment error last week');
|
||||
|
||||
const systemPrompt = `
|
||||
User Background:
|
||||
${context.userBackground.join('\n')}
|
||||
|
||||
Current Context:
|
||||
${context.currentContext.join('\n')}
|
||||
|
||||
Relevant Information:
|
||||
${context.relevantMemories.map(m => m.content).join('\n')}
|
||||
`;
|
||||
```
|
||||
|
||||
```python Python
|
||||
async def get_full_context(user_id: str, user_query: str):
|
||||
# Single call gets both profile and search results
|
||||
response = requests.post(
|
||||
'https://api.supermemory.ai/v4/profile',
|
||||
headers={
|
||||
'Authorization': f'Bearer {os.getenv("SUPERMEMORY_API_KEY")}',
|
||||
'Content-Type': 'application/json'
|
||||
},
|
||||
json={
|
||||
'containerTag': user_id,
|
||||
'q': user_query # Include the user's query
|
||||
}
|
||||
)
|
||||
|
||||
data = response.json()
|
||||
|
||||
return {
|
||||
'user_background': data['profile'].get('static', []),
|
||||
'current_context': data['profile'].get('dynamic', []),
|
||||
'relevant_memories': data.get('searchResults', {}).get('results', [])
|
||||
}
|
||||
|
||||
# Usage
|
||||
context = await get_full_context('user_123', 'deployment error last week')
|
||||
|
||||
system_prompt = f"""
|
||||
User Background:
|
||||
{chr(10).join(context['user_background'])}
|
||||
|
||||
Current Context:
|
||||
{chr(10).join(context['current_context'])}
|
||||
|
||||
Relevant Information:
|
||||
{chr(10).join(m['content'] for m in context['relevant_memories'])}
|
||||
"""
|
||||
```
|
||||
|
||||
</CodeGroup>
|
||||
|
||||
## Filtering with Threshold
|
||||
|
||||
Use the optional `threshold` parameter to filter search results by relevance score:
|
||||
|
||||
<CodeGroup>
|
||||
|
||||
```typescript TypeScript
|
||||
async function getHighQualityContext(userId: string, userQuery: string) {
|
||||
const response = await fetch('https://api.supermemory.ai/v4/profile', {
|
||||
method: 'POST',
|
||||
headers: {
|
||||
'Authorization': `Bearer ${process.env.SUPERMEMORY_API_KEY}`,
|
||||
'Content-Type': 'application/json'
|
||||
},
|
||||
body: JSON.stringify({
|
||||
containerTag: userId,
|
||||
threshold: 0.7, // Only include high-confidence results
|
||||
q: userQuery
|
||||
})
|
||||
});
|
||||
|
||||
const data = await response.json();
|
||||
|
||||
// Only highly relevant memories are included
|
||||
return data;
|
||||
}
|
||||
```
|
||||
|
||||
```python Python
|
||||
async def get_high_quality_context(user_id: str, user_query: str):
|
||||
response = requests.post(
|
||||
'https://api.supermemory.ai/v4/profile',
|
||||
headers={
|
||||
'Authorization': f'Bearer {os.getenv("SUPERMEMORY_API_KEY")}',
|
||||
'Content-Type': 'application/json'
|
||||
},
|
||||
json={
|
||||
'containerTag': user_id,
|
||||
'threshold': 0.7, # Only include high-confidence results
|
||||
'q': user_query
|
||||
}
|
||||
)
|
||||
|
||||
data = response.json()
|
||||
|
||||
# Only highly relevant memories are included
|
||||
return data
|
||||
```
|
||||
|
||||
</CodeGroup>
|
||||
|
||||
## Separate Profile and Search
|
||||
|
||||
For more control, you can call profile and search endpoints separately:
|
||||
|
||||
```typescript TypeScript
|
||||
async function advancedContext(userId: string, query: string) {
|
||||
// Parallel requests for profile and search
|
||||
const [profileRes, searchRes] = await Promise.all([
|
||||
fetch('https://api.supermemory.ai/v4/profile', {
|
||||
method: 'POST',
|
||||
headers: {
|
||||
'Authorization': `Bearer ${process.env.SUPERMEMORY_API_KEY}`,
|
||||
'Content-Type': 'application/json'
|
||||
},
|
||||
body: JSON.stringify({ containerTag: userId })
|
||||
}),
|
||||
fetch('https://api.supermemory.ai/v3/search', {
|
||||
method: 'POST',
|
||||
headers: {
|
||||
'Authorization': `Bearer ${process.env.SUPERMEMORY_API_KEY}`,
|
||||
'Content-Type': 'application/json'
|
||||
},
|
||||
body: JSON.stringify({
|
||||
q: query,
|
||||
containerTag: userId,
|
||||
limit: 5
|
||||
})
|
||||
})
|
||||
]);
|
||||
|
||||
const profile = await profileRes.json();
|
||||
const search = await searchRes.json();
|
||||
|
||||
return { profile: profile.profile, searchResults: search.results };
|
||||
}
|
||||
```
|
||||
|
||||
## Express.js Middleware
|
||||
|
||||
Add profile context to all authenticated requests:
|
||||
|
||||
```typescript TypeScript
|
||||
import express from 'express';
|
||||
|
||||
// Middleware to fetch user profile
|
||||
async function withUserProfile(req, res, next) {
|
||||
if (!req.user?.id) {
|
||||
return next();
|
||||
}
|
||||
|
||||
try {
|
||||
const response = await fetch('https://api.supermemory.ai/v4/profile', {
|
||||
method: 'POST',
|
||||
headers: {
|
||||
'Authorization': `Bearer ${process.env.SUPERMEMORY_API_KEY}`,
|
||||
'Content-Type': 'application/json'
|
||||
},
|
||||
body: JSON.stringify({ containerTag: req.user.id })
|
||||
});
|
||||
|
||||
req.userProfile = await response.json();
|
||||
} catch (error) {
|
||||
console.error('Failed to fetch profile:', error);
|
||||
req.userProfile = null;
|
||||
}
|
||||
|
||||
next();
|
||||
}
|
||||
|
||||
const app = express();
|
||||
|
||||
// Apply to all routes
|
||||
app.use(withUserProfile);
|
||||
|
||||
app.post('/chat', async (req, res) => {
|
||||
const { message } = req.body;
|
||||
|
||||
// Profile is automatically available
|
||||
const profile = req.userProfile?.profile;
|
||||
|
||||
// Use in your LLM call...
|
||||
});
|
||||
```
|
||||
|
||||
## Next.js API Route
|
||||
|
||||
```typescript TypeScript
|
||||
// app/api/chat/route.ts
|
||||
import { NextRequest, NextResponse } from 'next/server';
|
||||
|
||||
export async function POST(req: NextRequest) {
|
||||
const { userId, message } = await req.json();
|
||||
|
||||
// Fetch profile
|
||||
const profileRes = await fetch('https://api.supermemory.ai/v4/profile', {
|
||||
method: 'POST',
|
||||
headers: {
|
||||
'Authorization': `Bearer ${process.env.SUPERMEMORY_API_KEY}`,
|
||||
'Content-Type': 'application/json'
|
||||
},
|
||||
body: JSON.stringify({ containerTag: userId })
|
||||
});
|
||||
|
||||
const { profile } = await profileRes.json();
|
||||
|
||||
// Build context and call your LLM...
|
||||
const response = await generateResponse(message, profile);
|
||||
|
||||
return NextResponse.json({ response });
|
||||
}
|
||||
```
|
||||
|
||||
## AI SDK Integration
|
||||
|
||||
For the cleanest integration, use the Supermemory AI SDK middleware:
|
||||
|
||||
```typescript TypeScript
|
||||
import { generateText } from "ai"
|
||||
import { withSupermemory } from "@supermemory/tools/ai-sdk"
|
||||
import { openai } from "@ai-sdk/openai"
|
||||
|
||||
// Simple setup - profiles automatically injected
|
||||
const model = withSupermemory(openai("gpt-4"), {
|
||||
containerTag: "user-123",
|
||||
customId: "conv-1",
|
||||
})
|
||||
|
||||
const result = await generateText({
|
||||
model,
|
||||
messages: [{ role: "user", content: "Help me with my current project" }]
|
||||
})
|
||||
// Model automatically has access to user's profile!
|
||||
```
|
||||
|
||||
<Card title="AI SDK User Profiles" icon="triangle" href="/integrations/ai-sdk">
|
||||
Learn more about automatic profile injection with the AI SDK
|
||||
</Card>
|
||||
|
|
@ -1,135 +0,0 @@
|
|||
---
|
||||
title: "User Profiles"
|
||||
description: "Automatically maintained user context that gives your LLMs instant, comprehensive knowledge about each user"
|
||||
sidebarTitle: "Overview"
|
||||
icon: "user"
|
||||
---
|
||||
|
||||
User profiles are **automatically maintained collections of facts about your users** that Supermemory builds from all their interactions and content. Think of it as a persistent "about me" document that's always up-to-date and instantly accessible.
|
||||
|
||||
<CardGroup cols={2}>
|
||||
<Card title="Instant Context" icon="bolt">
|
||||
No search queries needed - comprehensive user information is always ready
|
||||
</Card>
|
||||
<Card title="Auto-Updated" icon="rotate">
|
||||
Profiles update automatically as users interact with your system
|
||||
</Card>
|
||||
<Card title="Two-Tier Structure" icon="layer-group">
|
||||
Static facts + dynamic context for perfect personalization
|
||||
</Card>
|
||||
<Card title="Zero Setup" icon="wand-magic-sparkles">
|
||||
Just ingest content normally - profiles build themselves
|
||||
</Card>
|
||||
</CardGroup>
|
||||
|
||||
## Why Profiles?
|
||||
|
||||
Traditional memory systems rely entirely on search, which has fundamental limitations:
|
||||
|
||||
| Problem | With Search Only | With Profiles |
|
||||
|---------|-----------------|---------------|
|
||||
| **Context retrieval** | 3-5 search queries | 1 profile call |
|
||||
| **Response time** | 200-500ms | 50-100ms |
|
||||
| **Consistency** | Varies by search quality | Always comprehensive |
|
||||
| **Basic user info** | Requires specific queries | Always available |
|
||||
|
||||
**Search is too narrow**: When you search for "project updates", you miss that the user prefers bullet points, works in PST timezone, and uses specific terminology.
|
||||
|
||||
**Profiles provide the foundation**: Instead of repeatedly searching for basic context, profiles give your LLM a complete picture of who the user is.
|
||||
|
||||
## Static vs Dynamic
|
||||
|
||||
Profiles intelligently separate two types of information:
|
||||
|
||||

|
||||
|
||||
### Static Profile
|
||||
|
||||
Long-term, stable facts that rarely change:
|
||||
|
||||
- "Sarah Chen is a senior software engineer at TechCorp"
|
||||
- "Sarah specializes in distributed systems and Kubernetes"
|
||||
- "Sarah has a PhD in Computer Science from MIT"
|
||||
- "Sarah prefers technical documentation over video tutorials"
|
||||
|
||||
### Dynamic Profile
|
||||
|
||||
Recent context and temporary states:
|
||||
|
||||
- "Sarah is currently migrating the payment service to microservices"
|
||||
- "Sarah recently started learning Rust for a side project"
|
||||
- "Sarah is preparing for a conference talk next month"
|
||||
- "Sarah is debugging a memory leak in the authentication service"
|
||||
|
||||
## How It Works
|
||||
|
||||
Profiles are **automatically built and maintained** through Supermemory's ingestion pipeline:
|
||||
|
||||
<Steps>
|
||||
<Step title="Content Ingestion">
|
||||
When users add documents, chat, or any content to Supermemory, it goes through the standard ingestion workflow.
|
||||
</Step>
|
||||
|
||||
<Step title="Intelligence Extraction">
|
||||
AI analyzes the content to extract not just memories, but also facts about the user themselves.
|
||||
</Step>
|
||||
|
||||
<Step title="Profile Operations">
|
||||
The system generates profile operations (add, update, or remove facts) based on the new information.
|
||||
</Step>
|
||||
|
||||
<Step title="Automatic Updates">
|
||||
Profiles are updated in real-time, ensuring they always reflect the latest information.
|
||||
</Step>
|
||||
</Steps>
|
||||
|
||||
<Note>
|
||||
You don't need to manually manage profiles - they build themselves as users interact with your system.
|
||||
</Note>
|
||||
|
||||
## Profiles + Search
|
||||
|
||||
Profiles don't replace search - they complement it:
|
||||
|
||||
<Steps>
|
||||
<Step title="Profile provides foundation">
|
||||
The user's profile gives your LLM comprehensive background context about who they are, what they know, and what they're working on.
|
||||
</Step>
|
||||
|
||||
<Step title="Search adds specificity">
|
||||
When you need specific information (like "error in deployment yesterday"), search finds those exact memories.
|
||||
</Step>
|
||||
|
||||
<Step title="Combined for perfect context">
|
||||
Your LLM gets both the broad understanding from profiles AND the specific details from search.
|
||||
</Step>
|
||||
</Steps>
|
||||
|
||||
### Example
|
||||
|
||||
User asks: **"Can you help me debug this?"**
|
||||
|
||||
**Without profiles**: The LLM has no context about the user's expertise level, current projects, or debugging preferences.
|
||||
|
||||
**With profiles**: The LLM knows:
|
||||
- The user is a senior engineer (adjust technical level)
|
||||
- They're working on a payment service migration (likely context)
|
||||
- They prefer command-line tools over GUIs (tool suggestions)
|
||||
- They recently had issues with memory leaks (possible connection)
|
||||
|
||||
## Next Steps
|
||||
|
||||
<CardGroup cols={2}>
|
||||
<Card title="API Reference" icon="code" href="/user-profiles/api">
|
||||
Learn how to fetch and use profiles via the API
|
||||
</Card>
|
||||
<Card title="Code Examples" icon="laptop-code" href="/user-profiles/examples">
|
||||
See complete integration examples
|
||||
</Card>
|
||||
<Card title="AI SDK Integration" icon="triangle" href="/integrations/ai-sdk">
|
||||
Use the AI SDK for automatic profile injection
|
||||
</Card>
|
||||
<Card title="Use Cases" icon="lightbulb" href="/user-profiles/use-cases">
|
||||
Common patterns and applications
|
||||
</Card>
|
||||
</CardGroup>
|
||||
|
|
@ -1,153 +0,0 @@
|
|||
---
|
||||
title: "Profile Use Cases"
|
||||
description: "Common patterns and applications for user profiles"
|
||||
sidebarTitle: "Use Cases"
|
||||
icon: "lightbulb"
|
||||
---
|
||||
|
||||
## Personalized AI Assistants
|
||||
|
||||
The most common use case: building AI assistants that truly know your users.
|
||||
|
||||
**What profiles provide:**
|
||||
- User's expertise level (adjust technical depth)
|
||||
- Communication preferences (brief vs detailed, formal vs casual)
|
||||
- Tools and technologies they use
|
||||
- Current projects and priorities
|
||||
|
||||
**Example prompt enhancement:**
|
||||
|
||||
```typescript
|
||||
const systemPrompt = `You are assisting ${userName}.
|
||||
|
||||
Their background:
|
||||
${profile.static.join('\n')}
|
||||
|
||||
Current focus:
|
||||
${profile.dynamic.join('\n')}
|
||||
|
||||
Adjust your responses to match their expertise level and preferences.`;
|
||||
```
|
||||
|
||||
**Result:** An assistant that explains React hooks differently to a junior developer vs a senior architect.
|
||||
|
||||
## Customer Support Systems
|
||||
|
||||
Give support agents (or AI) instant context about customers.
|
||||
|
||||
**What profiles provide:**
|
||||
- Customer's product usage history
|
||||
- Previous issues and resolutions
|
||||
- Preferred communication channels
|
||||
- Technical proficiency level
|
||||
|
||||
**Benefits:**
|
||||
- No more "let me look up your account"
|
||||
- Agents immediately understand customer context
|
||||
- AI support can reference past interactions naturally
|
||||
|
||||
```typescript
|
||||
// Support agent dashboard
|
||||
async function loadCustomerContext(customerId: string) {
|
||||
const { profile } = await getProfile(customerId);
|
||||
|
||||
return {
|
||||
summary: profile.static, // Long-term customer info
|
||||
recentIssues: profile.dynamic // Current tickets, recent problems
|
||||
};
|
||||
}
|
||||
```
|
||||
|
||||
## Educational Platforms
|
||||
|
||||
Adapt learning content to each student's level and progress.
|
||||
|
||||
**What profiles provide:**
|
||||
- Learning style preferences
|
||||
- Completed courses and topics
|
||||
- Areas of strength and weakness
|
||||
- Current learning goals
|
||||
|
||||
**Example adaptation:**
|
||||
|
||||
```typescript
|
||||
// Profile might contain:
|
||||
// static: ["Visual learner", "Strong in algebra, struggles with geometry"]
|
||||
// dynamic: ["Currently studying calculus", "Preparing for AP exam"]
|
||||
|
||||
const tutorPrompt = `You're helping a student with:
|
||||
${profile.static.join('\n')}
|
||||
|
||||
Current focus: ${profile.dynamic.join('\n')}
|
||||
|
||||
Adapt explanations to their learning style and build on their strengths.`;
|
||||
```
|
||||
|
||||
## Development Tools
|
||||
|
||||
IDE assistants and coding tools that understand your codebase and habits.
|
||||
|
||||
**What profiles provide:**
|
||||
- Preferred languages and frameworks
|
||||
- Coding style and conventions
|
||||
- Current project context
|
||||
- Frequently used patterns
|
||||
|
||||
**Example:**
|
||||
|
||||
```typescript
|
||||
// Profile for a developer:
|
||||
// static: ["Prefers TypeScript", "Uses functional patterns", "Senior engineer"]
|
||||
// dynamic: ["Working on auth refactor", "Recently learning Rust"]
|
||||
|
||||
// Code assistant knows to:
|
||||
// - Suggest TypeScript solutions
|
||||
// - Use functional patterns in examples
|
||||
// - Provide senior-level explanations
|
||||
// - Connect suggestions to the auth refactor when relevant
|
||||
```
|
||||
|
||||
## Knowledge Base Assistants
|
||||
|
||||
Internal tools that understand each employee's role and responsibilities.
|
||||
|
||||
**What profiles provide:**
|
||||
- Department and role
|
||||
- Projects they're involved in
|
||||
- Access level and permissions context
|
||||
- Areas of expertise (for routing questions)
|
||||
|
||||
**Example:**
|
||||
|
||||
```typescript
|
||||
// HR assistant that knows:
|
||||
// - Employee's team and manager
|
||||
// - Their location/timezone
|
||||
// - Recent PTO requests
|
||||
// - Benefits elections
|
||||
|
||||
const response = await hrAssistant.answer(
|
||||
"When is my next performance review?",
|
||||
{ profile: employeeProfile }
|
||||
);
|
||||
// Can answer with specific dates, manager name, etc.
|
||||
```
|
||||
|
||||
## E-commerce Recommendations
|
||||
|
||||
Personalized shopping experiences beyond basic recommendation engines.
|
||||
|
||||
**What profiles provide:**
|
||||
- Style preferences
|
||||
- Size information
|
||||
- Past purchases and returns
|
||||
- Budget range
|
||||
- Occasions they shop for
|
||||
|
||||
**Example conversation:**
|
||||
|
||||
```
|
||||
User: "I need something for a wedding next month"
|
||||
|
||||
// Profile knows: prefers classic styles, size M, budget-conscious,
|
||||
// previously bought navy suits
|
||||
|
|
@ -171,17 +171,17 @@ import { supermemoryTools } from '@supermemory/tools/ai-sdk'
|
|||
|
||||
// Option 1: Agent tools (recommended for agentic flows)
|
||||
const result = await streamText({
|
||||
model: anthropic('claude-3-5-sonnet-20241022'),
|
||||
model: anthropic('claude-sonnet-4-5'),
|
||||
prompt: userMessage,
|
||||
tools: supermemoryTools(process.env.SUPERMEMORY_API_KEY, {
|
||||
containerTag: userId // singular string — never an array
|
||||
containerTags: [userId] // the tools config takes an array; API bodies use singular containerTag
|
||||
})
|
||||
})
|
||||
// Agent gets searchMemories, addMemory, fetchMemory tools
|
||||
|
||||
// Option 2: Profile middleware (automatic context injection)
|
||||
import { withSupermemory } from '@supermemory/tools/ai-sdk'
|
||||
const modelWithMemory = withSupermemory(anthropic('claude-3-5-sonnet-20241022'), {
|
||||
const modelWithMemory = withSupermemory(anthropic('claude-sonnet-4-5'), {
|
||||
containerTag: userId,
|
||||
customId: 'conversation-1',
|
||||
})
|
||||
|
|
@ -236,15 +236,14 @@ import Supermemory from 'supermemory'
|
|||
const client = new Supermemory()
|
||||
|
||||
// Search for relevant memories
|
||||
const results = await client.search({
|
||||
const results = await client.search.memories({
|
||||
q: userMessage,
|
||||
containerTag: userId,
|
||||
searchMode: 'hybrid', // Searches memories + document chunks
|
||||
limit: 5
|
||||
})
|
||||
|
||||
// Build context
|
||||
const context = results.results.map(r => r.memory || r.chunk).join('\n')
|
||||
const context = results.results.map(r => r.memory).join('\n')
|
||||
|
||||
// Send to LLM with context
|
||||
const messages = [
|
||||
|
|
|
|||
|
|
@ -1,64 +0,0 @@
|
|||
---
|
||||
title: "Integrate supermemory in your Zapier workflows"
|
||||
sidebarTitle: "Zapier"
|
||||
description: "Learn how to use the code block to integrate supermemory with Zapier and add memory to your automations."
|
||||
---
|
||||
|
||||
With Supermemory you can now easily add memory to your Zapier workflow steps. Here's how:
|
||||
|
||||
## Prerequisites
|
||||
- A Supermemory API Key. Get yours [here](https://console.supermemory.ai)
|
||||
|
||||
## Step-by-step tutorial
|
||||
|
||||
For this tutorial, we're building a simple flow that adds incoming emails in Gmail to Supermemory.
|
||||
|
||||
<Steps>
|
||||
<Step title="Make a flow">
|
||||
Open your Zapier account and click on 'Zap' to make a new automation.
|
||||

|
||||
</Step>
|
||||
<Step title="Add Gmail node">
|
||||
Add a new Gmail node that gets triggered on every new email. Connect to your Google account.
|
||||

|
||||
</Step>
|
||||
<Step title="Add code block">
|
||||
Now, add a new 'Code by Zapier' block. Set it up to run Python.
|
||||
|
||||
In the **Input Data** section, map the content field to the Gmail raw snippet.
|
||||
|
||||

|
||||
</Step>
|
||||
<Step title="Integrate Supermemory">
|
||||
Since we're ingesting data here, we'll use the add documents endpoint.
|
||||
|
||||
Add the following code block:
|
||||
|
||||
```python
|
||||
import requests
|
||||
|
||||
url = "https://api.supermemory.ai/v3/documents"
|
||||
|
||||
payload = { "content": inputData['content'], "containerTag": "gmail" }
|
||||
headers = {
|
||||
"Authorization": "Bearer YOUR_SM_API_KEY",
|
||||
"Content-Type": "application/json"
|
||||
}
|
||||
|
||||
response = requests.post(url, json=payload, headers=headers)
|
||||
|
||||
print(response.json())
|
||||
```
|
||||
|
||||
The `inputData['content']` field maps to the Gmail content fetched from Zapier.
|
||||
|
||||

|
||||
</Step>
|
||||
</Steps>
|
||||
|
||||
<Note>
|
||||
Sometimes Zapier might show an error on the first test run. It usually works right after. Weird bug, we know.
|
||||
</Note>
|
||||
|
||||
|
||||
You can perform other operations like search, filtering, user profiles, etc., by using other Supermemory API endpoints which can be found in our API Reference tab.
|
||||
Loading…
Add table
Reference in a new issue