This guide covers the vector store implementations available in flowllm, their APIs, and how to use them effectively.

📋 Overview

flowllm provides multiple vector store backends for different use cases:

  • LocalVectorStore (backend=local) - 📁 Simple file-based storage for development and small datasets
  • ChromaVectorStore (backend=chroma) - 🔮 Embedded vector database for moderate scale
  • EsVectorStore (backend=elasticsearch) - 🔍 Elasticsearch-based storage for production and large scale
  • MemoryVectorStore (backend=memory) - ⚡ In-memory storage for ultra-fast access and testing

All vector stores implement the BaseVectorStore interface, providing a consistent API across implementations.

📊 Comparison Table

Feature LocalVectorStore ChromaVectorStore EsVectorStore MemoryVectorStore
Storage File (JSONL) Embedded DB Elasticsearch In-Memory
Performance Medium Good Excellent Ultra-Fast
Scalability < 10K vectors < 1M vectors > 1M vectors < 1M vectors
Persistence ✅ Auto ✅ Auto ✅ Auto ⚠️ Manual
Setup Complexity 🟢 Simple 🟡 Medium 🔴 Complex 🟢 Simple
Dependencies None ChromaDB Elasticsearch None
Filtering ❌ Basic ✅ Metadata ✅ Advanced ❌ Basic
Concurrency ❌ Limited ✅ Good ✅ Excellent ❌ Single Process
Best For Development Local Apps Production Testing

🔄 Common API Methods

All vector store implementations share these core methods:

🔄 Async Support

All vector stores provide both synchronous and asynchronous versions of every method:

# Synchronous methods
store.search(query="example", workspace_id="workspace", top_k=5)
store.insert(nodes, workspace_id="workspace")

# Asynchronous methods (with async_ prefix)
await store.async_search(query="example", workspace_id="workspace", top_k=5)
await store.async_insert(nodes, workspace_id="workspace")

Workspace Management

# Check if workspace exists
store.exist_workspace(workspace_id: str) -> bool

# Create a new workspace
store.create_workspace(workspace_id: str, **kwargs)

# Delete a workspace
store.delete_workspace(workspace_id: str, **kwargs)

# Copy a workspace
store.copy_workspace(src_workspace_id: str, dest_workspace_id: str, **kwargs)

Data Operations

# Insert nodes (single or list)
store.insert(nodes: VectorNode | List[VectorNode], workspace_id: str, **kwargs)

# Delete nodes by ID
store.delete(node_ids: str | List[str], workspace_id: str, **kwargs)

# Search for similar nodes
store.search(query: str, workspace_id: str, top_k: int = 1, **kwargs) -> List[VectorNode]

# Iterate through workspace nodes
for node in store.iter_workspace_nodes(workspace_id: str, **kwargs):
    # Process each node

Import/Export

# Export workspace to file
store.dump_workspace(workspace_id: str, path: str | Path = "", callback_fn=None, **kwargs)

# Import workspace from file
store.load_workspace(workspace_id: str, path: str | Path = "", nodes: List[VectorNode] = None, 
                    callback_fn=None, **kwargs)

⚡ Vector Store Implementations

1. 📁 LocalVectorStore (backend=local)

A simple file-based vector store that saves data to local JSONL files.

💡 When to Use

  • Development and testing - No external dependencies required 🛠️
  • Small datasets - Suitable for datasets with < 10,000 vectors 📊
  • Single-user applications - Limited concurrent access support 👤

⚙️ Configuration

from flowllm.storage.vector_store import LocalVectorStore
from flowllm.embedding_model import OpenAICompatibleEmbeddingModel
from flowllm.utils.common_utils import load_env

# Load environment variables (for API keys)
load_env()

# Initialize embedding model
embedding_model = OpenAICompatibleEmbeddingModel(dimensions=64, model_name="text-embedding-v4")

# Initialize vector store
vector_store = LocalVectorStore(
    embedding_model=embedding_model,
    store_dir="./file_vector_store",  # Directory to store JSONL files
    batch_size=1024                   # Batch size for operations
)

💻 Example Usage

from flowllm.schema.vector_node import VectorNode

# Create workspace
workspace_id = "my_workspace"
vector_store.create_workspace(workspace_id)

# Create nodes
nodes = [
    VectorNode(
        unique_id="node1",
        workspace_id=workspace_id,
        content="Artificial intelligence is revolutionizing technology",
        metadata={"category": "tech", "source": "article1"}
    ),
    VectorNode(
        unique_id="node2",
        workspace_id=workspace_id,
        content="Machine learning enables data-driven insights",
        metadata={"category": "tech", "source": "article2"}
    )
]

# Insert nodes
vector_store.insert(nodes, workspace_id)

# Search
results = vector_store.search("What is AI?", workspace_id, top_k=2)
for result in results:
    print(f"Content: {result.content}")
    print(f"Metadata: {result.metadata}")
    print(f"Score: {result.metadata.get('score', 'N/A')}")

2. 🔮 ChromaVectorStore (backend=chroma)

An embedded vector database that provides persistent storage with advanced features.

💡 When to Use

  • Local development with persistence requirements 🏠
  • Medium-scale applications (10K - 1M vectors) 📈
  • Applications requiring metadata filtering 🔍

⚙️ Configuration

from flowllm.storage.vector_store import ChromaVectorStore
from flowllm.embedding_model import OpenAICompatibleEmbeddingModel
from flowllm.utils.common_utils import load_env

# Load environment variables
load_env()

# Initialize embedding model
embedding_model = OpenAICompatibleEmbeddingModel(dimensions=64, model_name="text-embedding-v4")

# Initialize vector store
vector_store = ChromaVectorStore(
    embedding_model=embedding_model,
    store_dir="./chroma_vector_store",  # Directory for Chroma database
    batch_size=1024                     # Batch size for operations
)

💻 Example Usage

from flowllm.schema.vector_node import VectorNode

workspace_id = "chroma_workspace"

# Check if workspace exists and create if needed
if not vector_store.exist_workspace(workspace_id):
    vector_store.create_workspace(workspace_id)

# Create nodes with metadata
nodes = [
    VectorNode(
        unique_id="node1",
        workspace_id=workspace_id,
        content="Deep learning models require large datasets",
        metadata={
            "category": "AI", 
            "difficulty": "advanced", 
            "topic": "deep_learning"
        }
    ),
    VectorNode(
        unique_id="node2",
        workspace_id=workspace_id,
        content="Transformer architecture revolutionized NLP",
        metadata={
            "category": "AI",
            "difficulty": "intermediate",
            "topic": "transformers"
        }
    )
]

# Insert nodes
vector_store.insert(nodes, workspace_id)

# Search
results = vector_store.search("deep learning", workspace_id, top_k=5)
for result in results:
    print(f"Content: {result.content}")
    print(f"Metadata: {result.metadata}")

3. 🔍 EsVectorStore (backend=elasticsearch)

Production-grade vector search using Elasticsearch with advanced filtering and scaling capabilities.

💡 When to Use

  • Production environments requiring high availability 🏭
  • Large-scale applications (1M+ vectors) 🚀
  • Complex filtering requirements on metadata 🎯

🛠️ Setup Elasticsearch

Before using EsVectorStore, set up Elasticsearch:

Option 1: Docker Run
# Pull the latest Elasticsearch image
docker pull docker.elastic.co/elasticsearch/elasticsearch-wolfi:9.0.0

# Run Elasticsearch container
docker run -p 9200:9200 \
  -e "discovery.type=single-node" \
  -e "xpack.security.enabled=false" \
  -e "xpack.license.self_generated.type=trial" \
  -e "http.host=0.0.0.0" \
  docker.elastic.co/elasticsearch/elasticsearch-wolfi:9.0.0
Environment Configuration
export FLOW_ES_HOSTS=http://localhost:9200

⚙️ Configuration

from flowllm.storage.vector_store import EsVectorStore
from flowllm.embedding_model import OpenAICompatibleEmbeddingModel
from flowllm.utils.common_utils import load_env
import os

# Load environment variables
load_env()

# Initialize embedding model
embedding_model = OpenAICompatibleEmbeddingModel(dimensions=64, model_name="text-embedding-v4")

# Initialize vector store
vector_store = EsVectorStore(
    embedding_model=embedding_model,
    hosts=os.getenv("FLOW_ES_HOSTS", "http://localhost:9200"),  # Elasticsearch hosts
    basic_auth=None,                                           # ("username", "password") for auth
    batch_size=1024                                           # Batch size for bulk operations
)

🎯 Advanced Filtering

EsVectorStore supports advanced filtering capabilities through the filter_dict parameter:

# Term filters (exact match)
term_filter = {
    "category": "technology",
    "author": "research_team"
}

# Range filters (numeric and date ranges)
range_filter = {
    "score": {"gte": 0.8},  # Score >= 0.8
    "confidence": {"gte": 0.5, "lte": 0.9},  # Between 0.5 and 0.9
    "timestamp": {"gte": "2024-01-01", "lte": "2024-12-31"}
}

# Combined filters (filters are combined with AND logic)
combined_filter = {
    "category": "AI",
    "confidence": {"gte": 0.9}
}

# Search with filters applied
results = vector_store.search("machine learning", workspace_id, top_k=10, filter_dict=combined_filter)

⚡ Performance Optimization

# Refresh index for immediate availability (useful after bulk inserts)
vector_store.insert(nodes, workspace_id, refresh=True)  # Auto-refresh
vector_store.refresh(workspace_id)  # Manual refresh

# Bulk operations with custom batch size
vector_store.insert(large_node_list, workspace_id, refresh=False)  # Skip refresh for speed
vector_store.refresh(workspace_id)  # Refresh once after all inserts

💻 Example Usage

from flowllm.schema.vector_node import VectorNode

# Define workspace
workspace_id = "production_workspace"

# Create workspace if needed
if not vector_store.exist_workspace(workspace_id):
    vector_store.create_workspace(workspace_id)

# Create nodes with rich metadata
nodes = [
    VectorNode(
        unique_id="doc1",
        workspace_id=workspace_id,
        content="Transformer architecture revolutionized NLP",
        metadata={
            "category": "AI",
            "subcategory": "NLP",
            "author": "research_team",
            "timestamp": "2024-01-15",
            "confidence": 0.95,
            "tags": ["transformer", "nlp", "attention"]
        }
    )
]

# Insert with refresh for immediate availability
vector_store.insert(nodes, workspace_id, refresh=True)

# Advanced search with filters
filter_dict = {
    "category": "AI",
    "confidence": {"gte": 0.9}
}

results = vector_store.search("transformer models", workspace_id, top_k=5, filter_dict=filter_dict)

for result in results:
    print(f"Score: {result.metadata.get('score', 'N/A')}")
    print(f"Content: {result.content}")
    print(f"Metadata: {result.metadata}")

4. ⚡ MemoryVectorStore (backend=memory)

An ultra-fast in-memory vector store that keeps all data in RAM for maximum performance.

💡 When to Use

  • Testing and development - Fastest possible operations for unit tests 🧪
  • Small to medium datasets that fit in memory (< 1M vectors) 💾
  • Applications requiring ultra-low latency search operations ⚡
  • Temporary workspaces that don't need persistence 🚀

⚙️ Configuration

from flowllm.storage.vector_store import MemoryVectorStore
from flowllm.embedding_model import OpenAICompatibleEmbeddingModel
from flowllm.utils.common_utils import load_env

# Load environment variables
load_env()

# Initialize embedding model
embedding_model = OpenAICompatibleEmbeddingModel(dimensions=64, model_name="text-embedding-v4")

# Initialize vector store
vector_store = MemoryVectorStore(
    embedding_model=embedding_model,
    store_dir="./memory_vector_store",  # Directory for backup/restore operations
    batch_size=1024                     # Batch size for operations
)

💻 Example Usage

from flowllm.schema.vector_node import VectorNode

workspace_id = "memory_workspace"

# Create workspace in memory
vector_store.create_workspace(workspace_id)

# Create nodes
nodes = [
    VectorNode(
        unique_id="mem_node1",
        workspace_id=workspace_id,
        content="Memory stores provide ultra-fast access to data",
        metadata={
            "category": "performance", 
            "type": "memory",
            "speed": "ultra_fast"
        }
    ),
    VectorNode(
        unique_id="mem_node2",
        workspace_id=workspace_id,
        content="In-memory databases excel at low-latency operations",
        metadata={
            "category": "performance",
            "type": "database",
            "latency": "low"
        }
    )
]

# Insert nodes (stored in memory)
vector_store.insert(nodes, workspace_id)

# Ultra-fast search
results = vector_store.search("fast memory access", workspace_id, top_k=2)
for result in results:
    print(f"Content: {result.content}")
    print(f"Score: {result.metadata.get('score', 'N/A')}")

# Optional: Save to disk for backup
vector_store.dump_workspace(workspace_id, path="./backup")

# Optional: Load from disk to memory
vector_store.load_workspace(workspace_id, path="./backup")

⚡ Performance Benefits

  • Zero I/O latency - All operations happen in RAM
  • Instant search results - No disk or network overhead
  • Perfect for testing - Fast setup and teardown
  • Memory efficient - Only stores what you need

🚨 Important Notes

  • Data is volatile - Lost when process ends unless explicitly saved
  • Memory usage - Entire dataset must fit in available RAM
  • No persistence - Use dump_workspace() to save to disk
  • Single process - Not suitable for distributed applications

📝 Working with VectorNode

The VectorNode class is the fundamental data unit for all vector stores:

from flowllm.schema.vector_node import VectorNode

# Create a node
node = VectorNode(
    unique_id="unique_identifier",     # Unique ID for the node (required)
    workspace_id="my_workspace",       # Workspace ID (required)
    content="Text content to embed",   # Content to be embedded (required)
    metadata={                         # Optional metadata
        "source": "document1",
        "category": "technology",
        "timestamp": "2024-08-29"
    },
    vector=None                        # Vector will be generated automatically if None
)

🔄 Import/Export Example

Export and import workspaces for backup or transfer:

# Export workspace to file
vector_store.dump_workspace(
    workspace_id="my_workspace",
    path="./backup_data"  # Directory to store the exported data
)

# Import workspace from file
vector_store.load_workspace(
    workspace_id="new_workspace",
    path="./backup_data"  # Directory containing the exported data
)

# Copy workspace within the same store
vector_store.copy_workspace(
    src_workspace_id="original_workspace",
    dest_workspace_id="copied_workspace"
)

🧩 Integration with Embedding Models

All vector stores require an embedding model to function:

from flowllm.embedding_model import OpenAICompatibleEmbeddingModel

# Initialize embedding model
embedding_model = OpenAICompatibleEmbeddingModel(
    dimensions=64,               # Embedding dimensions
    model_name="text-embedding-v4",  # Model name
    batch_size=32                # Batch size for embedding generation
)

# Pass to vector store (example with LocalVectorStore)
# You can also use: ChromaVectorStore, EsVectorStore, or MemoryVectorStore
vector_store = LocalVectorStore(
    embedding_model=embedding_model,
    store_dir="./vector_store"
)

🎉 This guide provides everything you need to work with vector stores in flowllm. Choose the implementation that best fits your use case and scale up as needed! ✨