Trieve
Trieve is an AI-native search and retrieval platform that offers hybrid search capabilities (semantic and full-text) and robust RAG (Retrieval Augmented Generation) infrastructure. Use Trieve when building AI applications that require accurate, context-aware information retrieval from custom data sources to ground LLM responses.
You are a seasoned architect of AI-driven applications, adept at integrating specialized search and retrieval services to enhance LLM performance. You consistently leverage Trieve to manage vast knowledge bases, ensuring your AI agents can access and synthesize the most relevant information for any given query. ## Key Points * **Secure API Keys**: Never expose your Trieve API key in client-side code. Use environment variables and proxy requests through a backend server if your frontend needs to interact with Trieve.
skilldb get search-services-skills/TrieveFull skill: 211 linesYou are a seasoned architect of AI-driven applications, adept at integrating specialized search and retrieval services to enhance LLM performance. You consistently leverage Trieve to manage vast knowledge bases, ensuring your AI agents can access and synthesize the most relevant information for any given query.
Core Philosophy
Trieve positions itself as the backbone for grounded AI, focusing on solving the "hallucination problem" by providing a reliable source of truth for your LLMs. Its core philosophy revolves around:
- Hybrid Search: Trieve combines the precision of semantic search (understanding the intent and meaning of a query) with the recall of traditional full-text keyword search. This ensures that even obscure but relevant keywords are captured, while also surfacing semantically similar content that might not contain exact keyword matches.
- RAG-as-a-Service: Beyond just search, Trieve provides the infrastructure for Retrieval Augmented Generation. It not only finds relevant snippets but also helps structure them in a way that is immediately consumable and effective for augmenting LLM prompts, reducing the complexity of building RAG pipelines yourself.
- Developer Experience: Trieve prioritizes ease of integration and use, offering robust SDKs and a clear API to get your data indexed and searchable quickly, allowing you to focus on your application's unique logic rather than re-inventing search or RAG.
You choose Trieve when your application demands highly accurate, context-aware information retrieval for AI agents, especially when dealing with large, complex, or dynamic datasets. It's ideal for building chatbots, intelligent assistants, knowledge management systems, and any application where an LLM needs to reference specific, up-to-date information.
Setup
To get started with Trieve, you first install the client library and then initialize it with your API key and dataset ID.
// npm install @trieve-ai/trieve-client
import { TrieveClient } from '@trieve-ai/trieve-client';
// Initialize the Trieve client
// Replace with your actual API key and dataset ID
const trieve = new TrieveClient({
apiKey: process.env.TRIEVE_API_KEY || 'YOUR_TRIEVE_API_KEY',
datasetId: process.env.TRIEVE_DATASET_ID || 'YOUR_TRIEVE_DATASET_ID',
});
// You can now use the 'trieve' client to interact with your dataset.
Ensure you manage your TRIEVE_API_KEY and TRIEVE_DATASET_ID securely, ideally using environment variables, and never expose them in client-side code.
Key Techniques
1. Indexing Documents
To make your data searchable, you need to upload it to Trieve. You can upload individual chunks or entire documents, letting Trieve handle chunking. When providing your own chunks, ensure they are coherent and small enough for LLMs to process effectively.
import { TrieveClient } from '@trieve-ai/trieve-client';
const trieve = new TrieveClient({
apiKey: process.env.TRIEVE_API_KEY!,
datasetId: process.env.TRIEVE_DATASET_ID!,
});
interface MyDocument {
id: string;
title: string;
content: string;
url: string;
author: string;
}
async function indexSingleDocument(doc: MyDocument) {
try {
const response = await trieve.createChunk({
chunk_html: doc.content, // HTML content is often preferred for better parsing
link: doc.url,
metadata: {
title: doc.title,
author: doc.author,
document_id: doc.id,
},
tracking_id: doc.id, // Unique ID for tracking and updating
});
console.log(`Successfully indexed document: ${doc.title}`);
return response;
} catch (error) {
console.error(`Failed to index document ${doc.title}:`, error);
throw error;
}
}
// Example usage:
await indexSingleDocument({
id: "doc_123",
title: "Understanding Trieve's Hybrid Search",
content: "<html><body><p>Trieve combines semantic vector search with traditional keyword matching...</p></body></html>",
url: "https://example.com/trieve-hybrid-search",
author: "AI Expert"
});
2. Performing Semantic and Hybrid Search
Trieve excels at returning semantically relevant chunks. You can perform a simple semantic search or leverage hybrid search for more comprehensive results.
import { TrieveClient } from '@trieve-ai/trieve-client';
const trieve = new TrieveClient({
apiKey: process.env.TRIEVE_API_KEY!,
datasetId: process.env.TRIEVE_DATASET_ID!,
});
async function performHybridSearch(query: string, page = 1, pageSize = 10) {
try {
const searchResults = await trieve.search({
query,
search_type: "hybrid", // Can be "semantic", "fulltext", or "hybrid"
page,
page_size: pageSize,
// You can add filters here, e.g., filters: { author: ["AI Expert"] }
});
console.log(`Found ${searchResults.total_pages} pages for "${query}"`);
for (const result of searchResults.chunks) {
console.log(`- Score: ${result.score}, Title: ${result.metadata?.title || 'N/A'}, Content snippet: ${result.chunk_html?.substring(0, 100)}...`);
}
return searchResults;
} catch (error) {
console.error(`Error during search for "${query}":`, error);
throw error;
}
}
// Example usage:
await performHybridSearch("how does trieve combine different search methods?");
3. Augmenting LLM Prompts with RAG
The primary use case for Trieve is to provide relevant context for LLMs. After retrieving chunks, you can format them into your prompt to ground the LLM's response.
import { TrieveClient } from '@trieve-ai/trieve-client';
// Assume you have an OpenAI client or similar LLM SDK
// import OpenAI from 'openai';
const trieve = new TrieveClient({
apiKey: process.env.TRIEVE_API_KEY!,
datasetId: process.env.TRIEVE_DATASET_ID!,
});
// const openai = new OpenAI({ apiKey: process.env.OPENAI_API_KEY });
async function getLLMResponseWithRAG(userQuery: string) {
try {
const searchResults = await trieve.search({
query: userQuery,
search_type: "hybrid",
page_size: 5, // Get a few top results
});
if (!searchResults.chunks || searchResults.chunks.length === 0) {
console.log("No relevant information found in Trieve.");
// Fallback to LLM without context or inform user
return "I couldn't find specific information on that in my knowledge base. Can I help with something else?";
}
// Format the retrieved chunks into a context string
const context = searchResults.chunks.map((chunk, index) =>
`Document ${index + 1} (Title: ${chunk.metadata?.title || 'N/A'}):\n${chunk.chunk_html}`
).join("\n\n---\n\n");
const prompt = `You are an AI assistant. Use the following information to answer the user's question. If the information does not contain the answer, state that you don't know.\n\nContext:\n${context}\n\nUser Question: ${userQuery}\n\nAnswer:`;
console.log("--- PROMPT SENT TO LLM ---");
console.log(prompt);
console.log("--------------------------");
// In a real application, you would send this prompt to an LLM
// Example with OpenAI (pseudo-code):
/*
const completion = await openai.chat.completions.create({
model: "gpt-4",
messages: [{ role: "user", content: prompt }],
max_tokens: 500,
});
return completion.choices[0].message.content;
*/
return "LLM response would go here, based on the context provided."; // Placeholder
} catch (error) {
console.error(`Error in RAG process for "${userQuery}":`, error);
throw error;
}
}
// Example usage:
await getLLMResponseWithRAG("Explain the benefits of Trieve for AI development.");
Best Practices
- Optimize Chunking Strategy: Trieve handles automatic chunking, but for optimal RAG, consider the coherence and size of your chunks. Aim for chunks that are small enough for an LLM to digest but large enough to contain complete thoughts or answers. Experiment with
chunk_sizeandoverlap_sizeif manually chunking. - Leverage Metadata: Attach rich metadata to your chunks (e.g.,
author,source_url,creation_date,document_type). This enables powerful filtering, faceting, and helps the LLM understand the provenance of the information. - Secure API Keys: Never expose your Trieve API key in client-side code. Use environment variables and proxy requests through a backend server if your frontend needs to interact with Trieve.
- Handle Empty Results Gracefully: Design your application to respond appropriately when Trieve returns no relevant chunks. This might involve a fallback to a general LLM response, a "no information found" message, or broadening the search.
- Iterate on Search Parameters: Experiment with
search_type(semantic,fulltext,hybrid),page_size, andfiltersto fine-tune the relevance of your search results for different query types. - Monitor and Re-index: Regularly monitor the quality of your retrieved results. As your data changes or your search requirements evolve, consider re-indexing documents or updating existing chunks for improved performance.
Anti-Patterns
Ignoring Data Quality. Indexing poorly formatted, noisy, or irrelevant data will degrade Trieve's retrieval performance and lead to poor RAG outcomes. Ensure your input data is clean, well-structured, and relevant to the queries you expect.
Over-reliance on Default Chunking. While convenient, Trieve's automatic chunking might not always be optimal for highly structured or domain-specific content. Manually pre-chunking your data into semantically coherent units can significantly improve retrieval accuracy.
Generic Queries for RAG. Sending overly broad or vague user queries directly to Trieve can result in less relevant context. Consider pre-processing user queries to make them more specific or generating multiple sub-queries to get richer context.
Hardcoding Dataset IDs and API Keys. Embedding sensitive credentials directly in your code is a security risk and makes deployment inflexible. Always use environment variables for API keys and dataset IDs.
Not Utilizing Filters. Ignoring Trieve's filtering capabilities means you're not fully leveraging your metadata. Filters are crucial for narrowing down search results based on specific criteria (e.g., author, document_type) and improving relevance.
Install this skill directly: skilldb add search-services-skills
Related Skills
Algolia
"Algolia: instant search, faceted search, InstantSearch.js/React, indexing, ranking, search analytics"
Elasticsearch
"Elasticsearch: full-text search, aggregations, mapping, bulk indexing, Node.js client, relevance tuning"
Fuse Js
Fuse.js is a lightweight, powerful fuzzy-search library for JavaScript that runs entirely client-side. It's ideal for quickly adding flexible, typo-tolerant search capabilities to web applications without server-side infrastructure.
Lunr
Lunr is a small, fast JavaScript search library for browsers and Node.js. It allows you to build a search index directly within your application, providing full-text search capabilities without a backend API or external service. It's ideal for static sites, documentation, or client-side applications requiring offline-capable search.
Manticore Search
"Manticore Search: open-source full-text search, SQL-based queries, real-time indexes, columnar storage, Elasticsearch-compatible API"
Meilisearch
"Meilisearch: self-hosted search engine, typo tolerance, faceting, filtering, sorting, REST API, JavaScript SDK"