Table of Contents

    Vector Databases (FAISS, OpenSearch, Pinecone)

    Generative AI and Large Language Models

    Vector Databases: FAISS, OpenSearch, and Pinecone

    Learn how vector databases store, index, filter, and retrieve high-dimensional embeddings for semantic search, Retrieval-Augmented Generation, recommendation systems, image retrieval, duplicate detection, and other similarity-based applications.

    Introduction

    Traditional keyword search finds documents containing the words supplied by a user. This works well when the query and the relevant document use matching words, identifiers, or phrases. However, two texts may express similar meanings while using different vocabulary.

    An embedding model converts text, images, audio, products, users, or other objects into numerical vectors. Semantically related objects are generally represented by vectors that are close to one another according to a selected similarity or distance measure.

    A vector database or vector-search system stores these vectors together with identifiers, metadata, and source information. It uses specialized indexes to retrieve the vectors most similar to a query vector.

    FAISS provides a high-performance library for building similarity-search indexes. OpenSearch combines vector retrieval with document search, filtering, and search-engine capabilities. Pinecone provides a managed vector-search platform with indexes, namespaces, records, and metadata filtering.

    Core principle: A vector database does not understand meaning independently. It efficiently searches numerical representations created by an embedding model.

    Learning Objectives

    By the End of This Lesson

    • Define a vector database
    • Explain how embeddings support semantic search
    • Distinguish vector search from keyword search
    • Understand exact and approximate nearest-neighbor search
    • Calculate cosine similarity, dot product, and Euclidean distance
    • Understand top-k vector retrieval
    • Explain embedding dimensionality
    • Understand vector normalization
    • Explain metadata and metadata filtering
    • Understand namespaces and logical isolation
    • Explain chunking for RAG ingestion
    • Build a FAISS index
    • Compare FAISS index strategies
    • Create an OpenSearch vector index
    • Run OpenSearch k-nearest-neighbor searches
    • Create and query a Pinecone index
    • Apply metadata filtering
    • Understand hybrid lexical and vector retrieval
    • Evaluate retrieval quality
    • Apply production security and monitoring controls

    Prerequisites

    Recommended Knowledge

    • Python programming
    • NumPy arrays
    • Basic linear algebra
    • Vectors and matrices
    • Natural Language Processing fundamentals
    • Transformer models
    • Text embeddings
    • REST API fundamentals
    • JSON documents
    • Retrieval-Augmented Generation fundamentals

    Packages Used in the Examples

    • NumPy
    • FAISS CPU
    • sentence-transformers
    • OpenSearch Python client
    • Pinecone Python SDK
    python -m pip install \
      numpy \
      faiss-cpu \
      sentence-transformers \
      opensearch-py \
      pinecone
    Compatibility requirement: Validate the operating system, Python version, package versions, network access, authentication, embedding model, and selected vector platform before implementing a production workflow.

    What Is a Vector?

    A vector is an ordered list of numerical values. In Machine Learning, a vector can represent the learned characteristics of a sentence, document, image, product, customer, or another object.

    Example Vector
    \[ \mathbf{x} = \begin{bmatrix} 0.12 & -0.47 & 0.81 & 0.09 \end{bmatrix} \]
    Term Meaning
    Vector An ordered numerical representation
    Dimension The number of values contained in a vector
    Embedding A learned vector representation of an object
    Vector Space The multidimensional space containing the vectors
    Query Vector The embedding used to search the index
    Neighbor A stored vector close to the query under the selected measure

    What Is an Embedding?

    An embedding is a dense numerical representation created by a trained model. Embeddings attempt to preserve useful relationships among objects in a vector space.

    Embedding Function
    \[ f \left( \text{object} \right) = \mathbf{x} \in \mathbb{R}^{d} \]
    Embedding Pipeline
    Text or Other Content → Embedding Model → Dense Vector
    Compatibility rule: Stored vectors and query vectors must use compatible embedding models, dimensions, normalization rules, and preprocessing.

    What Is a Vector Database?

    A vector database stores embeddings and provides indexes and query operations optimized for similarity-based retrieval.

    Component Purpose
    Record ID Uniquely identifies an indexed object or chunk
    Vector Stores the numerical embedding
    Metadata Stores searchable attributes and source context
    Index Organizes vectors for efficient retrieval
    Similarity Metric Defines how vector closeness is calculated
    Filter Restricts eligible records using metadata conditions
    Namespace or Collection Provides logical organization or isolation
    Query Operation Returns the nearest or highest-scoring records

    Keyword Search vs Vector Search

    Area Keyword Search Vector Search
    Primary Match Terms, tokens, and lexical patterns Closeness between embeddings
    Best For Names, identifiers, exact phrases, and rare terms Semantic similarity and paraphrased meaning
    Input Text query Query embedding
    Main Dependency Tokenizer, analyzer, and lexical index Embedding model, similarity measure, and vector index
    Weakness May miss semantically related text using different words May miss exact identifiers or return semantically close but unsuitable content
    Retrieval principle: Keyword and vector retrieval are complementary. Hybrid search can combine lexical precision with semantic similarity.

    Nearest-Neighbor Search

    Nearest-neighbor search finds stored vectors closest to a query vector according to a selected distance or similarity function.

    Nearest Neighbor
    \[ i^{*} = \arg\min_i d \left( \mathbf{q}, \mathbf{x}_i \right) \]

    Here, \(\mathbf{q}\) is the query vector, \(\mathbf{x}_i\) is an indexed vector, and \(d\) is the selected distance function.

    Top-k Retrieval
    \[ \operatorname{TopK} \left( \mathbf{q} \right) = \left\{ \mathbf{x}_{i_1}, \mathbf{x}_{i_2}, \ldots, \mathbf{x}_{i_k} \right\} \]

    Similarity and Distance Measures

    Measure Interpretation
    Cosine Similarity Compares the direction of two vectors
    Dot Product Measures alignment and is influenced by vector magnitude
    Euclidean Distance Measures straight-line distance in vector space
    Cosine Similarity
    \[ \operatorname{cos} \left( \mathbf{x}, \mathbf{y} \right) = \frac{ \mathbf{x} \cdot \mathbf{y} }{ \lVert \mathbf{x} \rVert_2 \lVert \mathbf{y} \rVert_2 } \]
    Dot Product
    \[ \mathbf{x} \cdot \mathbf{y} = \sum_{j=1}^{d} x_j y_j \]
    Euclidean Distance
    \[ d \left( \mathbf{x}, \mathbf{y} \right) = \sqrt{ \sum_{j=1}^{d} \left( x_j-y_j \right)^2 } \]
    Metric-selection rule: Use the similarity measure recommended for the embedding model and keep the same convention during indexing, querying, evaluation, and production serving.

    Vector Normalization

    L2 normalization scales a non-zero vector to unit length.

    L2 Normalization
    \[ \hat{\mathbf{x}} = \frac{ \mathbf{x} }{ \lVert \mathbf{x} \rVert_2 } \]

    For unit-normalized vectors, cosine similarity equals the dot product. This permits cosine-oriented retrieval using an inner-product index when normalization is applied consistently.

    import numpy as np
    
    
    def l2_normalize(
        vectors
    ):
        vectors = np.asarray(
            vectors,
            dtype=np.float32
        )
    
        norms = np.linalg.norm(
            vectors,
            axis=1,
            keepdims=True
        )
    
        if np.any(
            norms == 0
        ):
            raise ValueError(
                "Zero-length vectors cannot "
                "be normalized safely."
            )
    
        return vectors / norms

    Exact vs Approximate Search

    Exact Search

    • Evaluates every eligible vector
    • Returns exact nearest neighbors under the selected measure
    • Useful as a retrieval-quality baseline
    • Cost grows with dataset size and vector dimension

    Approximate Search

    • Searches an optimized index structure
    • Reduces query work
    • Trades some recall for latency, memory, or throughput
    • Requires index-specific configuration and evaluation
    Evaluation requirement: Compare an approximate index with an exact-search baseline using representative queries before selecting production parameters.

    Common Vector Index Strategies

    Index Strategy General Idea Main Trade-Off
    Flat Compares the query with every vector Exact results with increasing query cost
    HNSW Uses a navigable multilayer proximity graph Fast retrieval with graph-memory and tuning requirements
    IVF Partitions vectors into clusters and searches selected partitions Faster search with training and recall trade-offs
    Product Quantization Compresses vectors into compact representations Lower memory use with approximation loss
    IVF-PQ Combines partitioning with compressed vector codes Efficient large-scale search with additional accuracy trade-offs
    Binary Index Indexes binary representations Requires a compatible encoding and distance measure

    Metadata and Filtering

    Metadata describes an indexed object without forming part of the dense embedding. Metadata filters restrict the set of records eligible for similarity search.

    {
        "id": "document-42-chunk-3",
        "vector": [
            0.12,
            -0.47,
            0.81
        ],
        "metadata": {
            "document_id": "document-42",
            "category": "technical-manual",
            "language": "en",
            "version": "3",
            "access_group": "engineering"
        }
    }

    Useful Metadata

    • Source document identifier
    • Chunk identifier
    • Title or section
    • Content category
    • Language
    • Document version
    • Publication or effective date
    • Tenant or business scope
    • Access-control attributes
    • Embedding-model version
    Authorization principle: Security filtering must occur before unauthorized content can be returned to the caller or supplied to a generative model.

    Namespaces and Collections

    Vector systems may organize records through indexes, collections, namespaces, shards, or other logical boundaries. These structures can support workload organization, lifecycle management, and retrieval isolation.

    Organization Strategy Example Use
    Separate Index Different embedding dimensions or independent workloads
    Namespace Logical partition within a compatible index
    Metadata Filter Restrict records by category, version, tenant, or authorization
    Document Collection Group content sharing a lifecycle or schema
    Isolation caution: Logical organization is not automatically equivalent to a security boundary. Verify the access-control behavior of the selected platform.

    Chunking for Vector Retrieval

    Long documents are commonly divided into smaller chunks before embeddings are created. Chunking controls how much meaning and context each vector represents.

    Chunking Strategy General Approach
    Fixed Characters Splits text by an approximate character count
    Fixed Tokens Splits using the embedding model's tokenizer
    Sentence-Based Preserves sentence boundaries
    Paragraph-Based Preserves paragraph structure
    Section-Aware Uses headings and document hierarchy
    Semantic Chunking Uses content changes to determine boundaries
    Parent-Child Chunking Retrieves small chunks while returning broader parent context
    Chunking trade-off: Small chunks can improve retrieval precision but lose context. Large chunks preserve context but may contain unrelated material and consume more downstream tokens.

    Simple Overlapping Chunker

    def create_overlapping_chunks(
        text,
        chunk_size,
        overlap
    ):
        if chunk_size <= 0:
    
            raise ValueError(
                "chunk_size must be positive."
            )
    
        if (
            overlap < 0
            or overlap >= chunk_size
        ):
            raise ValueError(
                "overlap must be greater than "
                "or equal to zero and smaller "
                "than chunk_size."
            )
    
        words = str(
            text
        ).split()
    
        step_size = (
            chunk_size
            -
            overlap
        )
    
        chunks = []
    
        for start_index in range(
            0,
            len(
                words
            ),
            step_size
        ):
            chunk_words = words[
                start_index:
                start_index + chunk_size
            ]
    
            if not chunk_words:
                break
    
            chunks.append(
                " ".join(
                    chunk_words
                )
            )
    
            if (
                start_index
                +
                chunk_size
                >=
                len(
                    words
                )
            ):
                break
    
        return chunks
    Educational scope: This example splits by whitespace. Production ingestion may require tokenizer-aware, structure-aware, language-aware, table-aware, or multimodal chunking.

    Vector Ingestion Pipeline

    Ingestion Flow
    Collect → Parse → Clean → Chunk → Embed → Validate → Index
    1

    Collect Authorized Content

    Retrieve documents or records from approved sources and preserve their source identity.

    2

    Parse the Content

    Extract text and approved structural information from the source format.

    3

    Clean and Normalize

    Remove unsupported artifacts while preserving meaningful structure, context, and traceability.

    4

    Create Chunks

    Divide content using a strategy appropriate for the document, embedding model, and retrieval objective.

    5

    Generate Embeddings

    Use an approved and versioned embedding model.

    6

    Validate Records

    Verify identifiers, dimensions, finite values, metadata, authorization, duplicates, and source references.

    7

    Index the Records

    Store vectors and metadata in the selected vector-search system.

    8

    Record Lineage

    Preserve content, parser, chunker, embedding, index, and pipeline versions.

    Validate Embeddings Before Indexing

    import numpy as np
    
    
    def validate_embeddings(
        embeddings,
        expected_dimension
    ):
        embeddings = np.asarray(
            embeddings,
            dtype=np.float32
        )
    
        if embeddings.ndim != 2:
    
            raise ValueError(
                "Embeddings must be a "
                "two-dimensional array."
            )
    
        if embeddings.shape[
            1
        ] != expected_dimension:
    
            raise ValueError(
                "Embedding dimension does "
                "not match the index."
            )
    
        if not np.isfinite(
            embeddings
        ).all():
    
            raise ValueError(
                "Embeddings contain non-finite values."
            )
    
        if embeddings.shape[
            0
        ] == 0:
    
            raise ValueError(
                "At least one embedding is required."
            )
    
        return embeddings

    Generate Text Embeddings

    from sentence_transformers import SentenceTransformer
    
    
    embedding_model_id = (
        "sentence-transformers/"
        "all-MiniLM-L6-v2"
    )
    
    
    embedding_model = SentenceTransformer(
        embedding_model_id
    )
    
    
    documents = [
        "MLOps automates and governs the Machine Learning lifecycle.",
        "A feature store manages reusable features for training and inference.",
        "Vector search retrieves objects using embedding similarity.",
        "Model monitoring tracks production quality and operational behavior."
    ]
    
    
    document_embeddings = (
        embedding_model.encode(
            documents,
            convert_to_numpy=True,
            normalize_embeddings=True,
            show_progress_bar=False
        )
        .astype(
            "float32"
        )
    )
    
    
    print(
        document_embeddings.shape
    )
    Model-selection notice: The embedding model is used for demonstration. Evaluate approved models using your domain, language, retrieval, latency, licensing, privacy, and deployment requirements.

    What Is FAISS?

    FAISS is a similarity-search and clustering library for dense vectors. It provides multiple index structures and CPU and GPU implementations for supported workflows.

    FAISS Capability Purpose
    Flat Index Provides exact similarity search
    IVF Index Provides partition-based approximate search
    HNSW Index Provides graph-based approximate retrieval
    Product Quantization Compresses indexed vector representations
    Batch Search Processes multiple query vectors together
    GPU Indexes Uses compatible accelerators for supported indexes
    Architectural distinction: FAISS is primarily an indexing and search library. A complete database service may require additional persistence, metadata, filtering, authorization, replication, APIs, and operational management.

    Build an Exact FAISS Index

    import faiss
    import numpy as np
    
    
    document_embeddings = np.asarray(
        document_embeddings,
        dtype=np.float32
    )
    
    
    dimension = document_embeddings.shape[
        1
    ]
    
    
    faiss_index = faiss.IndexFlatIP(
        dimension
    )
    
    
    faiss_index.add(
        document_embeddings
    )
    
    
    print(
        {
            "dimension": dimension,
            "indexed_vectors": (
                faiss_index.ntotal
            )
        }
    )
    Similarity configuration: This example uses inner product with normalized vectors to support cosine-oriented retrieval.

    Search the FAISS Index

    query_text = (
        "How can semantic similarity "
        "be used to retrieve information?"
    )
    
    
    query_embedding = (
        embedding_model.encode(
            [
                query_text
            ],
            convert_to_numpy=True,
            normalize_embeddings=True,
            show_progress_bar=False
        )
        .astype(
            "float32"
        )
    )
    
    
    top_k = 3
    
    
    scores, indices = faiss_index.search(
        query_embedding,
        top_k
    )
    
    
    results = []
    
    
    for score, index_position in zip(
        scores[
            0
        ],
        indices[
            0
        ]
    ):
        if index_position == -1:
            continue
    
        results.append(
            {
                "document": documents[
                    index_position
                ],
                "score": float(
                    score
                )
            }
        )
    
    
    print(
        results
    )
    Score caution: A similarity score is useful only within the selected embedding, normalization, metric, and index configuration. It is not a universal percentage of correctness.

    Use Explicit IDs with FAISS

    import faiss
    import numpy as np
    
    
    base_index = faiss.IndexFlatIP(
        dimension
    )
    
    
    id_index = faiss.IndexIDMap2(
        base_index
    )
    
    
    vector_ids = np.array(
        [
            101,
            102,
            103,
            104
        ],
        dtype=np.int64
    )
    
    
    id_index.add_with_ids(
        document_embeddings,
        vector_ids
    )
    
    
    scores, retrieved_ids = (
        id_index.search(
            query_embedding,
            top_k
        )
    )
    
    
    print(
        retrieved_ids
    )
    ID principle: Use stable IDs and keep the relationship between each FAISS ID and its source document, chunk, metadata, version, and authorization record in controlled storage.

    Save and Load a FAISS Index

    import faiss
    from pathlib import Path
    
    
    index_path = Path(
        "artifacts/document_index.faiss"
    )
    
    
    index_path.parent.mkdir(
        parents=True,
        exist_ok=True
    )
    
    
    faiss.write_index(
        id_index,
        str(
            index_path
        )
    )
    
    
    loaded_index = faiss.read_index(
        str(
            index_path
        )
    )
    
    
    print(
        loaded_index.ntotal
    )
    Persistence requirement: Version the FAISS index together with its embedding model, normalization rule, metric, source corpus, IDs, metadata store, and build configuration.

    Build a FAISS HNSW Index

    import faiss
    
    
    hnsw_neighbors = 32
    
    
    hnsw_index = (
        faiss.IndexHNSWFlat(
            dimension,
            hnsw_neighbors,
            faiss.METRIC_INNER_PRODUCT
        )
    )
    
    
    hnsw_index.hnsw.efConstruction = 100
    
    hnsw_index.hnsw.efSearch = 64
    
    
    hnsw_index.add(
        document_embeddings
    )
    
    
    scores, indices = hnsw_index.search(
        query_embedding,
        top_k
    )
    HNSW tuning: Neighbor count, construction settings, and search settings affect memory, build time, query latency, and retrieval recall. Select them using measured evidence.

    Build a FAISS IVF Index

    import faiss
    
    
    number_of_partitions = 16
    
    
    quantizer = faiss.IndexFlatIP(
        dimension
    )
    
    
    ivf_index = faiss.IndexIVFFlat(
        quantizer,
        dimension,
        number_of_partitions,
        faiss.METRIC_INNER_PRODUCT
    )
    
    
    if document_embeddings.shape[
        0
    ] < number_of_partitions:
    
        raise ValueError(
            "More representative training "
            "vectors are required for this "
            "IVF configuration."
        )
    
    
    ivf_index.train(
        document_embeddings
    )
    
    
    ivf_index.add(
        document_embeddings
    )
    
    
    ivf_index.nprobe = 4
    
    
    scores, indices = ivf_index.search(
        query_embedding,
        top_k
    )
    IVF requirement: Train the index using a sufficiently large and representative vector sample. Validate the number of partitions and searched partitions against exact-search results.

    Evaluate Approximate Retrieval Recall

    Recall at k
    \[ \operatorname{Recall@k} = \frac{ \left| R_k \cap G_k \right| }{ \left| G_k \right| } \]

    Here, \(R_k\) is the approximate result set and \(G_k\) is the exact reference result set.

    def calculate_recall_at_k(
        retrieved_ids,
        ground_truth_ids
    ):
        retrieved_set = set(
            retrieved_ids
        )
    
        ground_truth_set = set(
            ground_truth_ids
        )
    
        if not ground_truth_set:
    
            raise ValueError(
                "Ground-truth IDs are required."
            )
    
        return (
            len(
                retrieved_set
                &
                ground_truth_set
            )
            /
            len(
                ground_truth_set
            )
        )

    FAISS Index Selection

    Requirement Possible Starting Point
    Exact Baseline Flat index
    Approximate Graph Search HNSW index
    Partition-Based Search IVF index
    Memory-Constrained Large Index Product-quantized or composite index
    Accelerated Compatible Workload Supported GPU index
    Selection rule: Measure recall, latency, throughput, build time, update behavior, memory, and operational complexity using representative vectors and queries.

    What Is OpenSearch Vector Search?

    OpenSearch can store vector fields alongside document content and metadata. This makes it suitable for applications combining vector similarity, lexical search, filters, and document-oriented search capabilities.

    OpenSearch Vector Capabilities

    • Vector fields
    • Approximate k-nearest-neighbor search
    • Exact or scoring-based vector queries where supported
    • HNSW and IVF configurations through compatible engines
    • Metadata and document filtering
    • Lexical search
    • Hybrid search patterns
    • Document lifecycle and index management

    Connect to OpenSearch

    import os
    
    from opensearchpy import OpenSearch
    
    
    opensearch_host = os.environ[
        "OPENSEARCH_HOST"
    ]
    
    
    opensearch_username = os.environ[
        "OPENSEARCH_USERNAME"
    ]
    
    
    opensearch_password = os.environ[
        "OPENSEARCH_PASSWORD"
    ]
    
    
    opensearch_client = OpenSearch(
        hosts=[
            {
                "host": opensearch_host,
                "port": 443
            }
        ],
        http_auth=(
            opensearch_username,
            opensearch_password
        ),
        use_ssl=True,
        verify_certs=True
    )
    Credential rule: Store credentials in an approved secret-management system. Do not place usernames, passwords, access keys, or certificates directly in source code.

    Create an OpenSearch Vector Index

    index_name = (
        "course-articles-v1"
    )
    
    
    index_definition = {
        "settings": {
            "index": {
                "knn": True
            }
        },
        "mappings": {
            "properties": {
                "chunk_id": {
                    "type": "keyword"
                },
                "document_id": {
                    "type": "keyword"
                },
                "title": {
                    "type": "text"
                },
                "chunk_text": {
                    "type": "text"
                },
                "category": {
                    "type": "keyword"
                },
                "language": {
                    "type": "keyword"
                },
                "access_group": {
                    "type": "keyword"
                },
                "embedding_model": {
                    "type": "keyword"
                },
                "content_vector": {
                    "type": "knn_vector",
                    "dimension": dimension,
                    "method": {
                        "name": "hnsw",
                        "space_type": "cosinesimil",
                        "engine": "lucene",
                        "parameters": {
                            "ef_construction": 128,
                            "m": 24
                        }
                    }
                }
            }
        }
    }
    
    
    if not opensearch_client.indices.exists(
        index=index_name
    ):
    
        opensearch_client.indices.create(
            index=index_name,
            body=index_definition
        )
    Mapping requirement: Vector dimensions and similarity configuration must match the embeddings written to the index. Mapping behavior cannot generally be changed safely after incompatible records are indexed.

    Index an OpenSearch Document

    document_record = {
        "chunk_id": "article-20-8-chunk-1",
        "document_id": "article-20-8",
        "title": (
            "Vector Databases"
        ),
        "chunk_text": documents[
            2
        ],
        "category": "generative-ai",
        "language": "en",
        "access_group": "learners",
        "embedding_model": (
            embedding_model_id
        ),
        "content_vector": (
            document_embeddings[
                2
            ].tolist()
        )
    }
    
    
    opensearch_client.index(
        index=index_name,
        id=document_record[
            "chunk_id"
        ],
        body=document_record,
        refresh=True
    )

    Search OpenSearch by Vector

    query_body = {
        "size": 3,
        "_source": [
            "chunk_id",
            "document_id",
            "title",
            "chunk_text",
            "category"
        ],
        "query": {
            "knn": {
                "content_vector": {
                    "vector": (
                        query_embedding[
                            0
                        ].tolist()
                    ),
                    "k": 3
                }
            }
        }
    }
    
    
    search_response = (
        opensearch_client.search(
            index=index_name,
            body=query_body
        )
    )
    
    
    for hit in search_response[
        "hits"
    ][
        "hits"
    ]:
        print(
            {
                "score": hit[
                    "_score"
                ],
                "source": hit[
                    "_source"
                ]
            }
        )

    OpenSearch Vector Search with a Filter

    filtered_query = {
        "size": 3,
        "_source": [
            "chunk_id",
            "title",
            "chunk_text",
            "category",
            "language"
        ],
        "query": {
            "knn": {
                "content_vector": {
                    "vector": (
                        query_embedding[
                            0
                        ].tolist()
                    ),
                    "k": 3,
                    "filter": {
                        "bool": {
                            "must": [
                                {
                                    "term": {
                                        "language": "en"
                                    }
                                },
                                {
                                    "term": {
                                        "access_group": (
                                            "learners"
                                        )
                                    }
                                }
                            ]
                        }
                    }
                }
            }
        }
    }
    
    
    filtered_response = (
        opensearch_client.search(
            index=index_name,
            body=filtered_query
        )
    )
    Security requirement: Build authorization filters from trusted server-side identity and policy information, not directly from user-controlled metadata.

    Hybrid Retrieval

    Hybrid retrieval combines lexical and vector signals. Lexical retrieval can preserve exact terms, while vector retrieval can identify semantically related content.

    Weighted Hybrid Score
    \[ S_{\text{hybrid}} = \lambda S_{\text{vector}} + \left( 1-\lambda \right) S_{\text{lexical}} \]
    Score-combination caution: Lexical and vector scores may have different scales. Use a tested normalization, ranking pipeline, rank fusion, or reranking strategy rather than combining raw scores blindly.

    What Is Pinecone?

    Pinecone is a managed vector-search platform. Applications can create an index, write records, organize them through namespaces, attach metadata, and retrieve similar records using vector or supported text-oriented search workflows.

    Pinecone Concepts

    • Index
    • Record
    • Vector
    • Metadata
    • Namespace
    • Upsert
    • Query or search
    • Metadata filter
    • Dense and sparse retrieval options

    Connect to Pinecone

    import os
    
    from pinecone import Pinecone
    
    
    pinecone_client = Pinecone(
        api_key=os.environ[
            "PINECONE_API_KEY"
        ]
    )
    API-key requirement: Keep the Pinecone API key in an approved secret store or protected environment variable. Do not publish it in notebooks, repositories, screenshots, or client-side code.

    Create a Pinecone Vector Index

    from pinecone import ServerlessSpec
    
    
    pinecone_index_name = (
        "course-articles-v1"
    )
    
    
    existing_indexes = {
        index_description[
            "name"
        ]
        for index_description in (
            pinecone_client.list_indexes()
        )
    }
    
    
    if (
        pinecone_index_name
        not in existing_indexes
    ):
        pinecone_client.create_index(
            name=pinecone_index_name,
            dimension=dimension,
            metric="cosine",
            spec=ServerlessSpec(
                cloud="aws",
                region=(
                    "replace-with-approved-region"
                )
            )
        )
    Deployment requirement: Select the cloud, region, index type, capacity, networking, and deletion-protection settings according to the current Pinecone API and your approved architecture.

    Target the Pinecone Index

    index_description = (
        pinecone_client.describe_index(
            pinecone_index_name
        )
    )
    
    
    pinecone_index = (
        pinecone_client.Index(
            host=index_description[
                "host"
            ]
        )
    )
    Client compatibility: Pinecone SDK interfaces can change across API versions. Use the documentation matching the installed SDK and the type of index you created.

    Upsert Vectors into Pinecone

    pinecone_records = []
    
    
    for position, (
        document_text,
        embedding
    ) in enumerate(
        zip(
            documents,
            document_embeddings
        ),
        start=1
    ):
        pinecone_records.append(
            {
                "id": (
                    f"course-chunk-{position}"
                ),
                "values": embedding.tolist(),
                "metadata": {
                    "document_id": (
                        "vector-database-lesson"
                    ),
                    "chunk_number": position,
                    "chunk_text": document_text,
                    "category": "generative-ai",
                    "language": "en",
                    "access_group": "learners",
                    "embedding_model": (
                        embedding_model_id
                    )
                }
            }
        )
    
    
    pinecone_index.upsert(
        vectors=pinecone_records,
        namespace="machine-learning-course"
    )
    Metadata-size principle: Store only metadata needed for retrieval, authorization, lineage, and display. Keep large source documents in appropriate content storage and reference them through stable identifiers.

    Query Pinecone

    pinecone_response = (
        pinecone_index.query(
            namespace=(
                "machine-learning-course"
            ),
            vector=(
                query_embedding[
                    0
                ].tolist()
            ),
            top_k=3,
            include_values=False,
            include_metadata=True
        )
    )
    
    
    for match in pinecone_response[
        "matches"
    ]:
        print(
            {
                "id": match[
                    "id"
                ],
                "score": match[
                    "score"
                ],
                "metadata": match[
                    "metadata"
                ]
            }
        )

    Pinecone Metadata Filtering

    filtered_pinecone_response = (
        pinecone_index.query(
            namespace=(
                "machine-learning-course"
            ),
            vector=(
                query_embedding[
                    0
                ].tolist()
            ),
            top_k=3,
            include_metadata=True,
            filter={
                "$and": [
                    {
                        "language": {
                            "$eq": "en"
                        }
                    },
                    {
                        "access_group": {
                            "$eq": "learners"
                        }
                    },
                    {
                        "category": {
                            "$in": [
                                "generative-ai",
                                "mlops"
                            ]
                        }
                    }
                ]
            }
        )
    )
    Filter requirement: Treat retrieval authorization as mandatory policy enforcement. Metadata filtering should not be an optional user-interface preference when restricted content is involved.

    FAISS vs OpenSearch vs Pinecone

    Area FAISS OpenSearch Pinecone
    Product Type Similarity-search library Search platform with vector capabilities Managed vector-search platform
    Deployment Embedded into an application or custom service Self-managed or managed OpenSearch environment Managed service
    Vector Index Control Detailed index selection and tuning Method and engine configuration Managed according to the selected Pinecone index and API
    Metadata Storage Requires application-managed metadata mapping Stores vector fields with document fields Stores metadata with indexed records
    Lexical Search Requires a separate implementation Built into the search platform Available according to the selected index and current search API
    Operational Management Application team manages persistence, APIs, scaling, and availability Requires search-cluster operations unless managed externally Infrastructure operations are managed by the service
    Suitable Starting Point Local search, research, custom systems, and exact baselines Applications combining search, filters, and vectors Teams preferring a managed vector-search service
    Selection principle: Choose a platform using retrieval quality, metadata requirements, lexical search, update rate, scale, availability, deployment model, security, compliance, team expertise, portability, and total operating cost.

    Vector Databases in RAG

    RAG Retrieval Flow
    User Query → Query Embedding → Filtered Vector Search → Reranking → Context Assembly → LLM Answer
    RAG Stage Responsibility
    Query Understanding Normalizes or expands the user's information need
    Embedding Creates a query vector compatible with the index
    Authorization Filter Restricts retrieval to permitted records
    Candidate Retrieval Returns semantically or lexically relevant chunks
    Reranking Reorders candidates using a more precise relevance model or rule
    Context Assembly Selects and formats evidence within the context budget
    Generation Produces an answer grounded in the supplied context
    Citation Connects answer claims to retrievable source records
    RAG limitation: A vector database retrieves candidates. It does not guarantee that the content is correct, current, sufficient, authorized, or used faithfully by the generative model.

    Reranking

    Reranking applies a second-stage model or scoring rule to the candidates returned by the initial retriever.

    Two-Stage Retrieval
    Fast Candidate Retrieval → Precise Reranking → Final Context

    Reranking Benefits

    • Uses richer query-document interaction
    • Can improve ordering among retrieved candidates
    • Can reduce weak context sent to the LLM
    • Allows broad first-stage retrieval followed by focused selection
    Latency trade-off: Reranking can improve relevance but adds model execution, latency, cost, and another component requiring evaluation and monitoring.

    Evaluate Retrieval Quality

    Metric Main Question
    Recall at k Did the top-k results contain the relevant evidence?
    Precision at k What proportion of the top-k results was relevant?
    Mean Reciprocal Rank How early did the first relevant result appear?
    Mean Average Precision How accurately were multiple relevant results ranked?
    Normalized Discounted Cumulative Gain How well did ranking preserve graded relevance?
    Filter Accuracy Were only eligible and authorized records returned?
    Retrieval Latency Did retrieval satisfy the operational objective?
    Empty-Result Rate How often did retrieval return no usable evidence?
    Precision at k
    \[ \operatorname{Precision@k} = \frac{ \text{Relevant Results in Top-k} }{ k } \]
    Reciprocal Rank
    \[ \operatorname{RR} = \frac{ 1 }{ \text{Rank of First Relevant Result} } \]

    Calculate Retrieval Metrics

    def precision_at_k(
        retrieved_ids,
        relevant_ids,
        k
    ):
        if k <= 0:
    
            raise ValueError(
                "k must be positive."
            )
    
        selected_ids = retrieved_ids[
            :k
        ]
    
        relevant_set = set(
            relevant_ids
        )
    
        relevant_count = sum(
            retrieved_id
            in relevant_set
            for retrieved_id in selected_ids
        )
    
        return (
            relevant_count
            /
            k
        )
    
    
    def reciprocal_rank(
        retrieved_ids,
        relevant_ids
    ):
        relevant_set = set(
            relevant_ids
        )
    
        for rank, retrieved_id in enumerate(
            retrieved_ids,
            start=1
        ):
            if retrieved_id in relevant_set:
    
                return 1.0 / rank
    
        return 0.0

    Build a Retrieval Evaluation Set

    {
        "query_id": "query-001",
        "query": "How does model monitoring detect production degradation?",
        "relevant_chunk_ids": [
            "monitoring-definition",
            "delayed-quality",
            "drift-detection"
        ],
        "required_filters": {
            "language": "en",
            "access_group": "learners"
        }
    }

    Evaluation-Set Requirements

    • Representative user queries
    • Simple and difficult information needs
    • Exact-term queries
    • Paraphrased semantic queries
    • Queries requiring metadata filters
    • Queries with multiple relevant documents
    • Queries for which no answer exists
    • Versioned relevance judgments
    • Independent evaluation examples

    Embedding and Index Versioning

    Asset Why Version It?
    Source Corpus Identifies the content available for retrieval
    Parser Controls extracted content and structure
    Chunker Controls chunk boundaries and overlap
    Embedding Model Defines vector meaning and dimension
    Normalization Influences similarity calculations
    Index Type Controls search behavior and trade-offs
    Index Parameters Control speed, recall, memory, and construction
    Metadata Schema Controls filtering, display, and authorization
    Reranker Controls final candidate ordering
    Retrieval Policy Controls top-k, filters, thresholds, and context selection

    Re-Embedding and Index Migration

    Changing the embedding model can alter vector dimensions and the geometry of the embedding space. Existing embeddings cannot generally be mixed safely with embeddings from an incompatible model.

    Controlled Migration
    Build New Index → Re-Embed Corpus → Evaluate → Shadow or Canary → Promote → Retire Old Index
    Migration principle: Build a separate versioned index for an incompatible embedding change. Do not silently write new-model vectors into an old-model index.

    Updates and Deletions

    Lifecycle Operations

    • Upsert new or changed chunks
    • Preserve stable record identifiers
    • Delete obsolete chunks
    • Remove superseded document versions
    • Propagate source deletion requests
    • Recalculate embeddings after content changes
    • Update metadata when authorization changes
    • Verify that removed records no longer appear in search
    • Record ingestion and deletion history
    Deletion requirement: Removing a source document does not automatically remove every stored chunk, vector, cache entry, generated copy, or backup. Implement an auditable deletion workflow.

    Security and Access Control

    Required Controls

    • Authenticate ingestion and query workloads
    • Apply least-privilege permissions
    • Encrypt network connections
    • Encrypt indexed data according to policy
    • Apply authorization filters before retrieval
    • Separate tenants or security scopes appropriately
    • Protect API keys and credentials
    • Validate uploaded document types and sizes
    • Prevent unauthorized index creation and deletion
    • Audit queries and administrative changes
    • Protect index backups
    • Apply data-retention and deletion requirements
    Unsafe Retrieval Search the complete vector index and remove unauthorized results only after they have been returned to the application.
    Controlled Retrieval Restrict the eligible search space using trusted identity and authorization data before content is returned or supplied to an LLM.

    Prompt Injection and Retrieved Content

    Retrieved text is untrusted data. A document may contain malicious, misleading, obsolete, or instruction-like content intended to alter the behavior of the downstream model.

    RAG Security Controls

    • Treat retrieved content as data rather than trusted instructions
    • Separate system instructions from retrieved context
    • Preserve source identifiers and citations
    • Apply authorization before retrieval
    • Inspect supported document types during ingestion
    • Detect suspicious instruction-like content where appropriate
    • Restrict tool execution and external actions
    • Require confirmation for consequential operations
    • Log retrieval and source-selection metadata safely
    • Test prompt-injection scenarios

    Vector Database Monitoring

    Monitoring Area Example Signal
    Availability Successful query and write rates
    Latency P50, P95, and P99 query duration
    Throughput Queries and writes processed per interval
    Index Size Vector count, storage, and metadata volume
    Ingestion Quality Rejected records, duplicates, and dimension mismatches
    Freshness Delay between source change and searchable vector
    Retrieval Quality Recall, precision, ranking, and empty-result rate
    Filter Quality Authorization and metadata-filter correctness
    Resource Use CPU, memory, disk, network, and accelerator use
    Cost Storage, indexing, embedding, transfer, and query consumption

    Retrieval Failure Handling

    Failure Controlled Response
    Embedding Service Unavailable Retry when safe, use approved cache, or return a controlled error
    Dimension Mismatch Reject the query and investigate model-index compatibility
    Vector Service Unavailable Use approved fallback retrieval or state that evidence is unavailable
    No Results Avoid unsupported generation and inform the application of insufficient evidence
    Low-Relevance Results Apply threshold, reranking, query rewriting, or controlled abstention
    Unauthorized Results Block the response, investigate policy enforcement, and preserve incident evidence
    Stale Index Correct ingestion and apply a controlled freshness response
    Partial Metadata Reject or quarantine records missing required authorization or lineage fields

    Cost and Performance Optimization

    Cost Driver Possible Control
    Embedding Generation Cache unchanged embeddings and re-embed only modified content
    Vector Dimension Select an evaluated embedding model appropriate for the task
    Duplicate Content Remove duplicates before embedding and indexing
    Large Metadata Store only retrieval and governance metadata
    High Top-k Retrieve enough candidates for quality without unnecessary context volume
    Exact Search Use approximate indexes when validated scale and latency require them
    Frequent Rebuilding Use versioned incremental ingestion where appropriate
    Unused Index Versions Apply retention and retirement policies after rollback needs expire
    Cross-Region Traffic Align embedding, index, application, and users with approved architecture

    Responsible Vector Retrieval

    Responsible-Use Requirements

    • Index only authorized content
    • Preserve source ownership and provenance
    • Protect personal and confidential information
    • Apply access-control filters before retrieval
    • Preserve source version and effective dates
    • Support correction and deletion workflows
    • Evaluate supported languages and domains
    • Measure quality across relevant query groups
    • Test no-answer and ambiguous-query behavior
    • Prevent unsupported claims when evidence is insufficient
    • Report source citations where appropriate
    • Maintain rollback and index-retirement procedures

    Common Vector Database Mistakes

    Mistake Store embeddings from different incompatible models in the same vector field.
    Correction Use versioned indexes or fields with a consistent embedding model, dimension, normalization rule, and metric.
    Mistake Treat similarity scores as confidence percentages.
    Correction Interpret scores within the measured model-index configuration and calibrate retrieval thresholds using evaluation data.
    Mistake Choose a large top-k value and send every result to the LLM.
    Correction Retrieve candidates, apply filters and reranking, remove duplicates, and assemble context within a controlled token budget.
    Mistake Apply authorization after vector retrieval.
    Correction Restrict the eligible result set before content is returned or processed downstream.
    Mistake Evaluate only query latency.
    Correction Evaluate relevance, recall, precision, filters, freshness, availability, security, cost, and downstream answer quality.
    Mistake Update the embedding model without rebuilding the index.
    Correction Build a versioned replacement index, re-embed the corpus, evaluate it, and promote it through a controlled migration.
    Mistake Assume FAISS alone provides a complete production database.
    Correction Add controlled metadata, persistence, APIs, authorization, availability, monitoring, backup, and lifecycle management.
    Mistake Ignore source deletion after indexing.
    Correction Propagate corrections and deletions to chunks, vectors, caches, replicas, and required backups through an auditable process.

    Troubleshooting

    Symptom Investigation
    Dimension Mismatch Embedding model, index mapping, preprocessing, and stored vector shape
    Irrelevant Results Chunking, embedding model, query formulation, metric, filters, and corpus quality
    Exact Terms Missing Lexical retrieval and hybrid-search design
    Repeated Results Duplicate chunks, overlapping content, and source-version handling
    Slow Queries Index type, top-k, filters, searched partitions, hardware, and network
    Low ANN Recall Search parameters, index training, vector distribution, and compression
    Missing Metadata Ingestion schema, serialization, mapping, and partial failures
    Old Content Returned Ingestion freshness, upsert IDs, obsolete-record deletion, and cache invalidation
    Unauthorized Results Identity mapping, server-side filters, namespaces, and policy enforcement
    Different Results Across Environments Embedding revision, normalization, index version, parameters, and corpus version

    Recommended Vector Database Workflow

    1

    Define the Retrieval Objective

    Identify the users, content, queries, relevance criteria, latency, scale, security, and downstream use.

    2

    Select the Embedding Model

    Evaluate domain, language, dimension, metric, quality, latency, privacy, licensing, and deployment requirements.

    3

    Prepare Authorized Content

    Parse, clean, deduplicate, classify, version, and protect source records.

    4

    Design the Chunking Strategy

    Select boundaries, size, overlap, parent context, and metadata through retrieval experiments.

    5

    Define Metadata and Security

    Select stable IDs, source fields, authorization attributes, versions, dates, and lifecycle information.

    6

    Build the Index

    Generate validated embeddings and create a versioned exact or approximate index.

    7

    Evaluate Retrieval

    Measure recall, precision, ranking, filtering, latency, throughput, and no-answer behavior.

    8

    Add Hybrid Retrieval and Reranking

    Combine complementary retrieval signals when measured evidence shows that they improve results.

    9

    Deploy and Monitor

    Track availability, latency, ingestion, freshness, quality, filters, cost, and downstream answer behavior.

    10

    Version and Improve

    Rebuild and evaluate new corpus, chunker, embedding, index, and retrieval-policy versions through controlled releases.

    Hands-On Practice

    1

    Create an Embedding Dataset

    Prepare a small approved or synthetic document collection with stable IDs and metadata.

    2

    Build an Exact FAISS Baseline

    Normalize embeddings, create a flat inner-product index, and inspect top-k results.

    3

    Build an Approximate FAISS Index

    Create an HNSW or IVF index and compare its recall and latency with exact search.

    4

    Create an OpenSearch Index

    Store vector, text, source, category, language, and access metadata in one document mapping.

    5

    Apply OpenSearch Filters

    Restrict vector retrieval using approved server-side language, category, and authorization filters.

    6

    Create a Pinecone Index

    Upsert versioned records into a namespace and query them through vector similarity.

    7

    Apply Pinecone Metadata Filtering

    Limit eligible results using authorized metadata conditions.

    8

    Evaluate the Three Systems

    Compare retrieval quality, latency, metadata behavior, operational responsibilities, security, portability, and cost.

    Knowledge Check

    1

    What is a vector database?

    Explain how it stores embeddings and retrieves nearby vectors using a similarity or distance measure.

    2

    What is an embedding?

    Explain how a trained model converts an object into a numerical representation.

    3

    How does semantic search differ from keyword search?

    Explain meaning-oriented vector matching compared with token-oriented lexical matching.

    4

    What does top-k retrieval return?

    Explain the k closest or highest-scoring eligible records.

    5

    Why normalize vectors?

    Explain how unit normalization supports consistent cosine-oriented inner-product retrieval.

    6

    How does approximate search differ from exact search?

    Explain the recall, latency, memory, and throughput trade-off.

    7

    Why is metadata filtering important?

    Explain how it restricts search by source, category, date, tenant, version, and authorization.

    8

    How does FAISS differ from a managed vector database?

    Explain the difference between a similarity-search library and a managed storage, query, availability, and lifecycle service.

    9

    Why combine vector and lexical retrieval?

    Explain how semantic similarity and exact-term matching provide complementary relevance signals.

    10

    Why rebuild an index after changing the embedding model?

    Explain changes in dimension, vector geometry, model meaning, normalization, and retrieval compatibility.

    Vector Database Readiness Checklist

    Confirm Before Production Use

    • The retrieval objective is documented
    • The intended users and applications are identified
    • The source corpus is authorized and versioned
    • The parser and chunker are versioned
    • The embedding model and immutable revision are recorded
    • The vector dimension is validated
    • The normalization policy is documented
    • The similarity metric matches the embedding model
    • Stable record and source identifiers are used
    • The metadata schema is versioned
    • Authorization metadata is required and validated
    • Chunk size and overlap are evaluated
    • Exact search provides a quality baseline
    • Approximate index recall is measured
    • Index-construction parameters are recorded
    • Search parameters are versioned
    • Representative evaluation queries are available
    • Relevance judgments are versioned
    • Recall, precision, ranking, and latency are measured
    • Metadata filters are tested
    • Unauthorized-result tests pass
    • No-answer behavior is defined
    • Low-relevance behavior is defined
    • Hybrid-search behavior is evaluated where applicable
    • Reranking is evaluated where applicable
    • Ingestion is idempotent
    • Duplicate chunks are controlled
    • Content updates and deletions are propagated
    • Index freshness is monitored
    • Query and ingestion failures generate actionable alerts
    • Credentials are stored securely
    • Network connections use approved protection
    • Backups and restoration are tested where required
    • Embedding-model migration is documented
    • Old indexes follow a retention and retirement policy
    • Downstream RAG quality and safety are monitored

    Lesson Summary

    Concept Main Outcome
    Embedding Represents an object as a dense numerical vector
    Vector Database Stores and retrieves vectors using similarity search
    Cosine Similarity Compares vector direction
    Dot Product Measures vector alignment
    Euclidean Distance Measures straight-line vector distance
    Exact Search Returns exact nearest neighbors under the selected metric
    Approximate Search Trades some recall for lower latency or resource use
    Metadata Filter Restricts eligible retrieval records
    FAISS Provides high-performance dense-vector indexing and search
    OpenSearch Combines vector, document, lexical, and filtered search
    Pinecone Provides managed vector indexing and retrieval
    Hybrid Search Combines lexical and semantic relevance
    Reranking Improves candidate ordering using a second-stage model or rule
    RAG Uses retrieved evidence to ground generated responses
    Retrieval Evaluation Measures relevance, ranking, filtering, latency, and completeness
    Governance Controls content, access, lineage, updates, deletion, and retirement

    Key Takeaway

    A vector database stores embeddings and retrieves records whose numerical representations are closest to a query vector. Embedding compatibility, vector dimensions, normalization, distance measures, index strategies, metadata filters, chunking, and source lineage all influence retrieval behavior. FAISS provides flexible local similarity-search indexes and detailed control. OpenSearch combines vector retrieval with document search, metadata, filtering, and lexical-search capabilities. Pinecone provides managed vector indexing, namespaces, records, and metadata-filtered retrieval. Reliable production retrieval requires more than storing vectors. It requires authorized content, point-to-source traceability, versioned embeddings, retrieval evaluation, server-side access control, freshness monitoring, deletion propagation, secure credentials, controlled migration, and responsible downstream use.

    Get Machine Learning updates by email

    Short, practical lessons and course updates from Rumman Ansari. No spam.