Data framework for your LLM application
—
Pending
Does it follow best practices?
Impact
Pending
No eval scenarios have been run
Pending
The risk profile of this skill
Core indexing functionality for creating searchable representations of documents using vector embeddings in LlamaIndex.TS.
import { VectorStoreIndex, Document } from "llamaindex";
// Or from specific submodules
import { VectorStoreIndex } from "llamaindex/indices";
import { SimpleVectorStore } from "llamaindex/vector-store";Vector indexing in LlamaIndex.TS converts documents into searchable vector representations using embedding models. The system supports multi-modal data (text, images, audio), various vector stores, and provides sophisticated similarity search capabilities including hybrid search, MMR (Maximum Marginal Relevance), and advanced filtering for retrieval augmented generation (RAG) applications.
The primary class for creating and managing vector-based indices.
class VectorStoreIndex extends BaseIndex<IndexDict> {
static async init(options: VectorIndexOptions): Promise<VectorStoreIndex>;
static async fromDocuments(
documents: Document[],
args?: VectorIndexOptions
): Promise<VectorStoreIndex>;
static async fromVectorStore(
vectorStore: BaseVectorStore,
args?: Omit<VectorIndexOptions, "storageContext">
): Promise<VectorStoreIndex>;
asQueryEngine(args?: VectorIndexQueryEngineOptions): RetrieverQueryEngine;
asRetriever(args?: VectorIndexRetrieverOptions): VectorIndexRetriever;
asChatEngine(args?: VectorIndexChatEngineOptions): ContextChatEngine;
async insertNodes(nodes: BaseNode[], options?: { logProgress?: boolean }): Promise<void>;
async insert(document: Document, args?: InsertArgs): Promise<void>;
async deleteRefDoc(refDocId: string, deleteFromDocStore?: boolean): Promise<void>;
async deleteNode(nodeId: string): Promise<void>;
async update(document: Document): Promise<void>;
async refresh(documents: Document[], args?: RefreshArgs): Promise<void>;
// Multi-modal vector store support
vectorStores: VectorStoreByType;
indexStore: BaseIndexStore;
embedModel?: BaseEmbedding;
}
interface VectorIndexOptions {
nodes?: BaseNode[];
storageContext?: StorageContext;
embedModel?: BaseEmbedding;
insertBatchSize?: number;
showProgress?: boolean;
storeNodesOverride?: boolean;
}
type VectorStoreByType = {
[ModalityType.TEXT]?: BaseVectorStore;
[ModalityType.IMAGE]?: BaseVectorStore;
[ModalityType.AUDIO]?: BaseVectorStore;
};Base interface that all vector stores implement with support for multi-modal data and advanced querying.
abstract class BaseVectorStore<Client = unknown, T = unknown> {
embedModel: BaseEmbedding;
abstract storesText: boolean;
abstract flatMetadata: boolean;
abstract client(): Client;
abstract add(embeddingResults: BaseNode[]): Promise<string[]>;
abstract delete(refDocId: string, deleteOptions?: object): Promise<void>;
abstract query(query: VectorStoreQuery<T>, options?: object): Promise<VectorStoreQueryResult>;
// Optional methods for enhanced functionality
async persist?(persistPath?: string, fsMap?: FileSystem): Promise<void>;
static async fromParams?(params: any): Promise<BaseVectorStore>;
}
interface VectorStoreConfig {
textKey?: string;
docIdKey?: string;
embeddingKey?: string;
metadataKey?: string;
chunkSize?: number;
addDataToDocStore?: boolean;
}In-memory vector store implementation, good for development and small datasets.
class SimpleVectorStore implements BaseVectorStore {
constructor(data?: SimpleVectorStoreData);
add(nodes: BaseNode[]): Promise<string[]>;
delete(refDocId: string): Promise<void>;
query(query: VectorStoreQuery): Promise<VectorStoreQueryResult>;
persist(persistPath?: string): Promise<void>;
static fromPersistDir(
persistDir?: string,
filename?: string
): Promise<SimpleVectorStore>;
getData(): SimpleVectorStoreData;
setData(data: SimpleVectorStoreData): void;
stores_text: boolean;
is_embedding_query: boolean;
flat_metadata: boolean;
}Query object for vector store operations with support for multiple query modes and multi-modal retrieval.
class VectorStoreQuery<T = unknown> {
constructor(args: {
queryEmbedding?: number[];
similarityTopK?: number;
docIds?: string[];
nodeIds?: string[];
queryStr?: string;
mode?: VectorStoreQueryMode;
alpha?: number;
beta?: number;
filters?: MetadataFilters;
mmrThreshold?: number;
sparseTopK?: number;
hybridTopK?: number;
modalityTopK?: Partial<Record<ModalityType, number>>;
outputFields?: string[];
embeddingField?: string;
});
queryEmbedding?: number[];
similarityTopK: number;
docIds?: string[];
nodeIds?: string[];
queryStr?: string;
mode: VectorStoreQueryMode;
alpha?: number; // Weight for dense retrieval in hybrid search
beta?: number; // Weight for sparse retrieval in hybrid search
filters?: MetadataFilters;
mmrThreshold?: number; // MMR diversity threshold
sparseTopK?: number; // Top-K for sparse retrieval
hybridTopK?: number; // Top-K for hybrid retrieval
modalityTopK?: Partial<Record<ModalityType, number>>; // Per-modality top-K
outputFields?: string[];
embeddingField?: string;
}
enum VectorStoreQueryMode {
DEFAULT = "default",
SPARSE = "sparse",
HYBRID = "hybrid",
SEMANTIC_HYBRID = "semantic_hybrid",
MMR = "mmr", // Maximum Marginal Relevance
SVM = "svm",
LOGISTIC_REGRESSION = "logistic_regression",
LINEAR_REGRESSION = "linear_regression",
}
enum ModalityType {
TEXT = "text",
IMAGE = "image",
AUDIO = "audio",
}Result object from vector store queries with enhanced result metadata.
class VectorStoreQueryResult {
constructor(args: {
nodes?: BaseNode[];
similarities?: number[];
ids?: string[];
metadata?: Record<string, any>[];
});
nodes?: BaseNode[];
similarities?: number[];
ids?: string[];
metadata?: Record<string, any>[];
}LlamaIndex.TS supports sophisticated metadata filtering with multiple operators and conditional logic.
interface MetadataFilters {
filters: MetadataFilter[];
condition?: FilterCondition;
}
interface MetadataFilter {
key: string;
value: FilterValue;
operator: FilterOperator;
}
type FilterValue = string | number | boolean | string[] | number[];
enum FilterOperator {
EQ = "==",
NE = "!=",
GT = ">",
GTE = ">=",
LT = "<",
LTE = "<=",
IN = "in",
NIN = "nin",
TEXT_MATCH = "text_match",
CONTAINS = "contains",
IS_EMPTY = "is_empty",
ANY = "any",
ALL = "all",
}
enum FilterCondition {
AND = "and",
OR = "or",
}// Complex conditional filtering
const complexFilters: MetadataFilters = {
filters: [
{ key: "category", value: ["tech", "finance"], operator: FilterOperator.IN },
{ key: "year", value: 2024, operator: FilterOperator.GTE },
{ key: "status", value: "published", operator: FilterOperator.EQ },
],
condition: FilterCondition.AND,
};
// Text matching and containment
const textFilters: MetadataFilters = {
filters: [
{ key: "title", value: "AI", operator: FilterOperator.TEXT_MATCH },
{ key: "tags", value: "machine-learning", operator: FilterOperator.CONTAINS },
],
condition: FilterCondition.OR,
};import { VectorStoreIndex, Document } from "llamaindex";
// Create documents
const documents = [
new Document({ text: "LlamaIndex is a data framework for LLM applications." }),
new Document({ text: "It helps connect custom data sources to large language models." }),
new Document({ text: "Vector databases enable semantic search over document collections." }),
];
// Create vector index (uses default embedding model from Settings)
const index = await VectorStoreIndex.fromDocuments(documents);
console.log("Index created successfully");// Create query engine
const queryEngine = index.asQueryEngine();
// Query the index
const response = await queryEngine.query("What is LlamaIndex?");
console.log("Response:", response.toString());
// Access source nodes
console.log("Sources:", response.sourceNodes?.map(node => node.id_));// Create retriever for more control
const retriever = index.asRetriever({
similarityTopK: 5, // Return top 5 most similar nodes
});
// Retrieve relevant nodes
const retrievedNodes = await retriever.retrieve("semantic search");
retrievedNodes.forEach((node, i) => {
console.log(`Node ${i}:`, node.text);
console.log(`Score:`, node.score);
});import { SimpleVectorStore, StorageContext } from "llamaindex";
// Create custom storage context with specific vector store
const vectorStore = new SimpleVectorStore();
const storageContext = StorageContext.fromDefaults({ vectorStore });
// Create index with custom storage
const index = await VectorStoreIndex.fromDocuments(documents, {
storageContext,
});import { SimpleVectorStore } from "llamaindex/vector-store";
// Save vector store to disk
await vectorStore.persist("./vector_store");
// Load vector store from disk
const loadedVectorStore = await SimpleVectorStore.fromPersistDir("./vector_store");
// Create index from loaded vector store
const loadedIndex = VectorStoreIndex.fromVectorStore(loadedVectorStore);import { VectorStoreIndex, OpenAIEmbedding } from "llamaindex";
// Create index with specific embedding model
const customEmbedding = new OpenAIEmbedding({
model: "text-embedding-3-large",
dimensions: 1536,
});
const index = await VectorStoreIndex.fromDocuments(documents, {
embed_model: customEmbedding,
});// Add documents with metadata
const documentsWithMeta = [
new Document({
text: "Financial report for Q1 2024",
metadata: { category: "finance", year: 2024, quarter: 1 }
}),
new Document({
text: "Technical documentation for API v2",
metadata: { category: "tech", version: "v2" }
}),
new Document({
text: "Marketing strategy for 2024",
metadata: { category: "marketing", year: 2024 }
}),
];
const index = await VectorStoreIndex.fromDocuments(documentsWithMeta);
// Query with metadata filters
const queryEngine = index.asQueryEngine({
preFilters: {
filters: [
{ key: "category", value: "finance", operator: "==" },
{ key: "year", value: 2024, operator: "==" }
]
}
});
const response = await queryEngine.query("What was the revenue?");// Insert single document
const newDoc = new Document({ text: "New information to add to the index." });
await index.insert(newDoc);
// Insert multiple documents
const moreDocs = [
new Document({ text: "Document 1" }),
new Document({ text: "Document 2" }),
];
for (const doc of moreDocs) {
await index.insert(doc);
}// Update existing document (requires same ID)
const updatedDoc = new Document({
text: "Updated content",
id_: "existing-doc-id"
});
await index.update(updatedDoc);// Delete by document ID
await index.deleteDocument("doc-id-to-delete");
// Delete specific nodes
await index.deleteNodes(["node-id-1", "node-id-2"]);// Refresh index with updated documents
const refreshedDocs = [
new Document({ text: "Updated content 1", id_: "doc-1" }),
new Document({ text: "Updated content 2", id_: "doc-2" }),
];
await index.refresh(refreshedDocs);import { StorageContext, SimpleDocumentStore, SimpleIndexStore, SimpleVectorStore } from "llamaindex";
// Configure all storage components
const storageContext = StorageContext.fromDefaults({
docStore: new SimpleDocumentStore(),
indexStore: new SimpleIndexStore(),
vectorStore: new SimpleVectorStore(),
});
const index = await VectorStoreIndex.fromDocuments(documents, {
storageContext,
});// Create index with persistent storage
const persistDir = "./storage";
const storageContext = StorageContext.fromDefaults({
persistDir,
});
const index = await VectorStoreIndex.fromDocuments(documents, {
storageContext,
});
// Persist to disk
await storageContext.persist(persistDir);
// Load from disk
const loadedStorageContext = StorageContext.fromDefaults({
persistDir,
});// Process large document collections in batches
const batchSize = 100;
const largeDocs = /* large array of documents */;
for (let i = 0; i < largeDocs.length; i += batchSize) {
const batch = largeDocs.slice(i, i + batchSize);
if (i === 0) {
// Create index with first batch
index = await VectorStoreIndex.fromDocuments(batch);
} else {
// Add subsequent batches
for (const doc of batch) {
await index.insert(doc);
}
}
console.log(`Processed ${Math.min(i + batchSize, largeDocs.length)} documents`);
}import { Settings } from "llamaindex";
// Configure for memory efficiency
Settings.chunkSize = 512; // Smaller chunks
Settings.chunkOverlap = 10; // Less overlap
// Use streaming for large operations
const queryEngine = index.asQueryEngine();
const stream = await queryEngine.query("query", { stream: true });
for await (const chunk of stream) {
console.log(chunk.response);
}import { BaseRetriever } from "llamaindex";
class CustomRetriever implements BaseRetriever {
async retrieve(query: string): Promise<NodeWithScore[]> {
// Custom retrieval logic
const vectorRetriever = index.asRetriever({ similarityTopK: 3 });
const nodes = await vectorRetriever.retrieve(query);
// Apply custom scoring or filtering
return nodes.filter(node => node.score! > 0.7);
}
}
const customRetriever = new CustomRetriever();
const queryEngine = index.asQueryEngine({ retriever: customRetriever });import { ResponseSynthesizer } from "llamaindex";
const responseSynthesizer = new ResponseSynthesizer({
responseMode: "tree_summarize", // Use hierarchical summarization
});
const queryEngine = index.asQueryEngine({
responseSynthesizer,
});
const response = await queryEngine.query("Complex multi-part question");// Configure for your use case
const productionIndex = await VectorStoreIndex.fromDocuments(documents, {
storageContext: StorageContext.fromDefaults({
persistDir: "./production_storage", // Persistent storage for production
}),
showProgress: true, // Show progress for large datasets
});
// Configure retrieval parameters
const queryEngine = productionIndex.asQueryEngine({
retriever: productionIndex.asRetriever({
similarityTopK: 5, // Adjust based on your needs
}),
});try {
const index = await VectorStoreIndex.fromDocuments(documents);
const response = await index.asQueryEngine().query("test query");
console.log(response.toString());
} catch (error) {
console.error("Indexing failed:", error);
// Handle specific error types
if (error.message.includes("embedding")) {
console.error("Check your embedding model configuration");
}
}import { Settings } from "llamaindex";
// Enable debug mode for detailed logging
Settings.debug = true;
// Monitor index size and performance
console.log("Vector store data:", vectorStore.getData());
console.log("Number of nodes:", vectorStore.getData().embeddingDict.size);