Semantic Search
Trix uses vector embeddings for semantic search, meaning queries are matched based on meaning rather than exact keywords. This allows natural language queries to find relevant memories even when the exact words differ.
import { Trix } from '@trixdb/client';
const trix = new Trix({ apiKey: process.env.TRIX_API_KEY });
// These queries will find similar memories
const result1 = await trix.memories.list({ q: 'user preferences' });
const result2 = await trix.memories.list({ q: 'what does the user like?' });
const result3 = await trix.memories.list({ q: 'previous conversations' });
// All will match semantically similar content
result1.data.forEach(m => {
console.log(`[${m.score.toFixed(2)}] ${m.content}`);
});No need for exact keyword matching - Trix understands the meaning behind your queries. A search for "user interface settings" will match memories about "dark mode preferences" even without shared keywords.
Search Modes
Trix supports three search modes to give you control over how queries are matched:
Beyond mode selection, Trix's retrieval can plan multi-step (multi-hop) recall for complex questions, run several sub-queries and fuse them with reciprocal rank fusion (RRF), and re-rank candidates with a cross-encoder for precision — automatically. Tune it per request with a pipeline preset.
| Mode | Description | Best For |
|---|---|---|
hybrid | Combines semantic and full-text search (default) | General purpose queries, best overall results |
semantic | Pure vector similarity matching | Conceptual queries, finding related ideas |
fulltext | Traditional keyword matching | Exact phrases, specific terminology |
// Hybrid search (default) - combines semantic and full-text
const hybrid = await trix.memories.list({
q: 'dark theme settings',
mode: 'hybrid'
});
// Semantic only - pure vector similarity
const semantic = await trix.memories.list({
q: 'dark theme settings',
mode: 'semantic'
});
// Full-text only - keyword matching
const fulltext = await trix.memories.list({
q: 'dark theme settings',
mode: 'fulltext'
});
// Compare results
console.log('Hybrid:', hybrid.data.length, 'results');
console.log('Semantic:', semantic.data.length, 'results');
console.log('Fulltext:', fulltext.data.length, 'results');Similarity Threshold
Filter results by minimum similarity score to ensure high-confidence matches:
// Only return high-confidence matches
const result = await trix.memories.list({
q: 'user preferences',
spaceId: 'user_123',
threshold: 0.7, // Minimum similarity score (0-1)
limit: 10
});
result.data.forEach(memory => {
console.log(`[${memory.score.toFixed(2)}] ${memory.content}`);
});
// Very strict threshold for precise matches
const precise = await trix.memories.list({
q: 'API authentication token',
threshold: 0.85
});
// Looser threshold to find more related content
const broad = await trix.memories.list({
q: 'user interface',
threshold: 0.5
});Topic-based Search
Trix uses LLM-powered topic extraction to identify themes and subjects within your memories. Topics provide a high-level categorization that complements semantic search with explicit subject matter identification.
What are Topics?
Topics are automatically extracted labels that describe what a memory is about. Each topic includes a category, relevance score, and optional metadata about why it was identified.
| Category | Examples | Description |
|---|---|---|
TECHNOLOGY | programming, cloud computing, AI/ML | Technical and software topics |
BUSINESS | marketing, finance, strategy | Business and commerce topics |
SCIENCE | physics, biology, research | Scientific and research topics |
PERSONAL | preferences, hobbies, relationships | Personal life and interests |
CREATIVE | writing, design, art | Creative and artistic topics |
HEALTH | fitness, nutrition, medical | Health and wellness topics |
EDUCATION | learning, courses, skills | Educational and learning topics |
GENERAL | miscellaneous, uncategorized | Topics that don't fit other categories |
Get Topics for a Memory
// Get a memory with its extracted topics
const memory = await trix.memories.get('mem_abc123');
console.log('Topics:', memory.topics);
// Access topic details
memory.topics.forEach(topic => {
console.log(`[${topic.category}] ${topic.name}: ${topic.relevance.toFixed(2)}`);
});Search by Topic
// Search for memories with a specific topic
const result = await trix.memories.list({
topic: 'react',
spaceId: 'user_123'
});
console.log(`Found ${result.data.length} memories about React`);
// Search with topic and semantic query combined
const combined = await trix.memories.list({
q: 'best practices',
topic: 'react',
spaceId: 'user_123'
});
// Search multiple topics (OR logic)
const multiTopic = await trix.memories.list({
topics: ['react', 'vue', 'angular'],
spaceId: 'user_123'
});
// Filter by topic category
const techTopics = await trix.memories.list({
topic_category: 'TECHNOLOGY',
spaceId: 'user_123'
});Topics are extracted using LLM enrichment, which runs automatically when memories are created. You can also manually trigger enrichment for existing memories.
Search Filters
Combine semantic search with filters for precise results. Filters can be combined in any combination to narrow down your search.
Basic Filters
// Combine multiple filters
const result = await trix.memories.list({
q: 'project requirements',
spaceId: 'project_alpha',
tags: ['requirements', 'specs'],
type: 'text',
created_after: '2024-01-01',
created_before: '2024-06-01',
limit: 20
});
// Filter by metadata
const metadataFiltered = await trix.memories.list({
q: 'user activity',
metadata: {
status: 'approved',
priority: 'high'
}
});Quality Score Filtering
// Only return high-quality memories
const highQuality = await trix.memories.list({
q: 'user preferences',
min_quality: 0.7,
spaceId: 'user_123'
});
// Find memories that need improvement
const lowQuality = await trix.memories.list({
max_quality: 0.4,
spaceId: 'user_123'
});Pinned & Protected Filters
// Only return pinned memories
const pinnedOnly = await trix.memories.list({
q: 'important',
is_pinned: true,
spaceId: 'user_123'
});
// Filter by protection level
const protectedMemories = await trix.memories.list({
protection_level: ['soft', 'hard'],
spaceId: 'user_123'
});LLM Enrichment
LLM enrichment extracts additional structured information from your memories, including topics, summaries, entities, and quality scores. This metadata powers advanced search features like topic-based filtering and quality scoring.
What Enrichment Provides
| Field | Description | Use Case |
|---|---|---|
topics | Extracted subject matter themes with categories | Topic-based search and filtering |
summary | Concise one-line summary of the memory | Quick previews, list displays |
entities | Named entities (people, places, products, etc.) | Knowledge graph, entity search |
quality_score | 0-1 score based on clarity, completeness, etc. | Quality filtering, content improvement |
sentiment | Emotional tone (positive, negative, neutral) | Sentiment analysis, mood tracking |
language | Detected language of the content | Multi-language support |
Automatic Enrichment
By default, memories are enriched automatically when created. You can control this behavior per memory or at the space level.
// Enrichment happens automatically by default
const memory = await trix.memories.create({
content: 'User mentioned they prefer Python for data science',
spaceId: 'user_123'
});
// Access enrichment data
console.log('Topics:', memory.topics);
console.log('Summary:', memory.summary);
console.log('Entities:', memory.entities);
console.log('Quality:', memory.quality_score);
// Disable enrichment for a specific memory
const quickMemory = await trix.memories.create({
content: 'Quick note without enrichment',
enrich: false
});Enrichment uses LLM models to extract structured data from your memories. This happens asynchronously and typically completes within seconds.
Search Best Practices
- Use natural language queries for semantic search
- Combine filters for precise results
- Set appropriate thresholds for your use case
- Use topic filtering for categorical searches
- Filter by quality for RAG applications
- Leverage cluster scales for different contexts
- Over-filtering (too many constraints)
- Very low thresholds (noisy results)
- Very high thresholds (missing relevant data)
- Ignoring quality scores for production RAG
- Using full-text mode for conceptual queries
- Skipping enrichment for searchable content
RAG Optimization
// Optimized search for RAG context retrieval
async function getRAGContext(query: string, userId: string) {
const result = await trix.memories.list({
q: query,
spaceId: userId,
min_quality: 0.6,
threshold: 0.65,
cluster_scale: 'fine',
include_pinned: true,
limit: 10
});
return result.data.map(m => ({
content: m.content,
relevance: m.score,
quality: m.quality_score,
source: m.id
}));
}