mirror of
https://github.com/supermemoryai/supermemory.git
synced 2026-08-28 05:25:33 +00:00
feat(docs): v4 hybrid search parameter and examples (#621)
This commit is contained in:
parent
ff35a6bffc
commit
1dd602c52b
4 changed files with 394 additions and 11 deletions
|
|
@ -464,9 +464,232 @@ Combining features for comprehensive results:
|
|||
</Tab>
|
||||
</Tabs>
|
||||
|
||||
## Comon Use Cases
|
||||
## 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
|
||||
|
|
|
|||
|
|
@ -194,33 +194,65 @@ Companies like Composio [Rube.app](https://rube.app) use memories search for let
|
|||
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
|
||||
// Memories search (default mode)
|
||||
const results = await client.search.memories({
|
||||
q: "machine learning accuracy",
|
||||
limit: 5,
|
||||
containerTag: "research",
|
||||
threshold: 0.7,
|
||||
rerank: true
|
||||
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
|
||||
# Memories search (default mode)
|
||||
results = client.search.memories(
|
||||
q="machine learning accuracy",
|
||||
limit=5,
|
||||
container_tag="research",
|
||||
threshold=0.7,
|
||||
rerank=True
|
||||
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" \
|
||||
|
|
@ -229,7 +261,20 @@ Companies like Composio [Rube.app](https://rube.app) use memories search for let
|
|||
"limit": 5,
|
||||
"containerTag": "research",
|
||||
"threshold": 0.7,
|
||||
"rerank": true
|
||||
"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>
|
||||
|
|
@ -283,7 +328,7 @@ Companies like Composio [Rube.app](https://rube.app) use memories search for let
|
|||
|
||||
```
|
||||
|
||||
The `/v4/search` endpoint searches through and returns memories.
|
||||
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
|
||||
|
||||
|
|
|
|||
|
|
@ -205,6 +205,28 @@ These parameters are specific to `client.search.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**
|
||||
|
||||
|
|
|
|||
|
|
@ -114,6 +114,8 @@ Response from `client.search.documents()` and `client.search.execute()`:
|
|||
|
||||
Response from `client.search.memories()`:
|
||||
|
||||
When `searchMode="memories"` (default), all results are memory entries:
|
||||
|
||||
```json
|
||||
{
|
||||
"results": [
|
||||
|
|
@ -160,14 +162,101 @@ Response from `client.search.memories()`:
|
|||
}
|
||||
```
|
||||
|
||||
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.
|
||||
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">
|
||||
**Complete memory content**. Unlike document search which returns chunks, memory search returns the full memory text.
|
||||
<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">
|
||||
|
|
@ -189,7 +278,11 @@ Response from `client.search.memories()`:
|
|||
</ResponseField>
|
||||
|
||||
<ResponseField name="version" type="number | null" optional>
|
||||
Version number of this memory entry. Used for tracking memory evolution and relationships.
|
||||
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>
|
||||
|
|
|
|||
Loading…
Add table
Reference in a new issue