MCPcopy Index your code
hub / github.com/Dicklesworthstone/fast_vector_similarity

github.com/Dicklesworthstone/fast_vector_similarity @v0.1.5

Chat with this repo
repository ↗ · DeepWiki ↗ · release v0.1.5 ↗ · + Follow
29 symbols 67 edges 3 files 2 documented · 7% updated 4mo agov0.1.5 · 2026-02-25★ 430
What it actually does AI analysis from the code graph — generated when you open this
loading…
README

Fast Vector Similarity Library

Introduction

The Fast Vector Similarity Library is a high-performance Rust-based tool for efficiently computing similarity measures between vectors. It is ideal for data analysis, machine learning, and statistical tasks where comparing vectors is essential. The library now includes several advanced measures, performance optimizations, and Python bindings, allowing seamless integration with Python workflows.

Features

Similarity Measures

The library implements a range of classical and modern similarity measures, including:

  1. Spearman's Rank-Order Correlation (spearman_rho)
  2. Kendall's Tau Rank Correlation (kendall_tau) (optimized for faster computation with large datasets)
  3. Approximate Distance Correlation (approximate_distance_correlation) (vectorized for speed and accuracy)
  4. Jensen-Shannon Dependency Measure (jensen_shannon_dependency_measure) (revised for improved utility in dependency measurement)
  5. Hoeffding's D Measure (hoeffding_d)
  6. Normalized Mutual Information (normalized_mutual_information) (newly introduced for analyzing variable dependence)

Bootstrapping Technique

The library includes robust bootstrapping functionality to estimate the distribution of similarity measures. Bootstrapping offers improved confidence in the results by randomly resampling the dataset multiple times.

Performance Optimizations

Several enhancements have been introduced for optimal efficiency:

  • Parallel Processing: Utilizing the rayon crate for parallel computation, ensuring that operations scale with the number of CPU cores.
  • Efficient Algorithms: Algorithms like merge sort are used for inversion counting, which improves the speed of measures like Kendall's Tau.
  • Vectorized Operations: Many functions leverage vectorized operations using the ndarray crate to maximize performance in Rust.

Benchmarking and Verification

The library now includes a benchmarking suite that verifies the correctness of the numerical results while measuring performance gains from recent improvements. This ensures that any changes in computational speed do not affect accuracy (except in intended changes like the Jensen-Shannon measure).

Python Bindings

Seamless integration with Python is possible via bindings that expose core functionality. The library provides two key functions for Python users:

  • py_compute_vector_similarity_stats: For computing various vector similarity measures.
  • py_compute_bootstrapped_similarity_stats: For bootstrapping-based similarity calculations.

Both functions return results in JSON format, making them easy to work with in Python environments.

Installation

Rust

Add the library to your Rust project by including it in your Cargo.toml file.

Python

The Python bindings can be installed directly from PyPI:

pip install fast_vector_similarity

Use with Text Embedding Vectors from LLMs

This library is highly compatible with modern language models like Llama2, enabling easy analysis of text embeddings. It integrates with the output of services like Llama2 Embeddings FastAPI Service and can handle high-dimensional embeddings (e.g., 4096-dimensional vectors).

Example Workflow

  1. Load Embeddings into a DataFrame: Convert text embeddings from a JSON format into a Pandas DataFrame.
  2. Compute Similarities: Use the Fast Vector Similarity Library to compute similarity measures between embeddings, leveraging the optimized functions.
  3. Analyze Results: Generate a ranked list of most similar vectors based on measures like Hoeffding's D.

Example Python Code

Here’s a Python snippet demonstrating the use of the library with large embedding vectors:

import time
import numpy as np
import json
import pandas as pd
import fast_vector_similarity as fvs
from random import choice

def convert_embedding_json_to_pandas_df(file_path):
    # Read the JSON file
    with open(file_path, 'r') as file:
        data = json.load(file)
    # Extract the text and embeddings
    texts = [item['text'] for item in data]
    embeddings = [item['embedding'] for item in data]
    # Determine the total number of vectors and the dimensions of each vector
    total_vectors = len(embeddings)
    vector_dimensions = len(embeddings[0]) if total_vectors > 0 else 0
    # Print the total number of vectors and dimensions
    print(f"Total number of vectors: {total_vectors}")
    print(f"Dimensions of each vector: {vector_dimensions}")
    # Convert the embeddings into a DataFrame
    df = pd.DataFrame(embeddings, index=texts)
    return df

def apply_fvs_to_vector(row_embedding, query_embedding):
    params = {
        "vector_1": query_embedding.tolist(),
        "vector_2": row_embedding.tolist(),
        "similarity_measure": "all"
    }
    similarity_stats_str = fvs.py_compute_vector_similarity_stats(json.dumps(params))
    return json.loads(similarity_stats_str)

def main():
    length_of_test_vectors = 15000
    print(f"Generating 2 test vectors of length {length_of_test_vectors}...")
    vector_1 = np.linspace(0., length_of_test_vectors - 1, length_of_test_vectors)
    vector_2 = vector_1 ** 0.2 + np.random.rand(length_of_test_vectors)
    print("Generated vector_1 using linear spacing and vector_2 using vector_1 with a power of 0.2 and some random noise.\n")

    similarity_measure = "all" # Or specify a particular measure
    params = {
        "vector_1": vector_1.tolist(),
        "vector_2": vector_2.tolist(),
        "similarity_measure": similarity_measure
    }

    # Time the exact similarity calculation
    print("Computing Exact Similarity Measures...")
    start_time_exact = time.time()
    similarity_stats_str = fvs.py_compute_vector_similarity_stats(json.dumps(params))
    similarity_stats_json = json.loads(similarity_stats_str)
    elapsed_time_exact = time.time() - start_time_exact
    print(f"Time taken for exact calculation: {elapsed_time_exact:.5f} seconds")

    # Print results
    print("_______________________________________________________________________________________________________________________________________________\n")
    print("Spearman's rho:", similarity_stats_json["spearman_rho"])
    print("Kendall's tau:", similarity_stats_json["kendall_tau"])
    print("Distance Correlation:", similarity_stats_json["approximate_distance_correlation"])
    print("Jensen-Shannon Dependency Measure:", similarity_stats_json["jensen_shannon_dependency_measure"])
    print("Normalized Mutual Information:", similarity_stats_json["normalized_mutual_information"])
    print("Hoeffding's D:", similarity_stats_json["hoeffding_d"])
    print("_______________________________________________________________________________________________________________________________________________\n")

    # Bootstrapped calculations
    number_of_bootstraps = 2000
    n = 15
    sample_size = int(length_of_test_vectors / n)

    print(f"Computing Bootstrapped Similarity Measures with {number_of_bootstraps} bootstraps and a sample size of {sample_size}...")
    start_time_bootstrapped = time.time()
    params_bootstrapped = {
        "x": vector_1.tolist(),
        "y": vector_2.tolist(),
        "sample_size": sample_size,
        "number_of_bootstraps": number_of_bootstraps,
        "similarity_measure": similarity_measure
    }
    bootstrapped_similarity_stats_str = fvs.py_compute_bootstrapped_similarity_stats(json.dumps(params_bootstrapped))
    bootstrapped_similarity_stats_json = json.loads(bootstrapped_similarity_stats_str)
    elapsed_time_bootstrapped = time.time() - start_time_bootstrapped
    print(f"Time taken for bootstrapped calculation: {elapsed_time_bootstrapped:.5f} seconds")

    time_difference = abs(elapsed_time_exact - elapsed_time_bootstrapped)
    print(f"Time difference between exact and robust bootstrapped calculations: {time_difference:.5f} seconds")

    # Print bootstrapped results
    print("_______________________________________________________________________________________________________________________________________________\n")
    print("Number of Bootstrap Iterations:", bootstrapped_similarity_stats_json["number_of_bootstraps"])
    print("Bootstrap Sample Size:", bootstrapped_similarity_stats_json["sample_size"])
    print("\nRobust Spearman's rho:", bootstrapped_similarity_stats_json["spearman_rho"])
    print("Robust Kendall's tau:", bootstrapped_similarity_stats_json["kendall_tau"])
    print("Robust Distance Correlation:", bootstrapped_similarity_stats_json["approximate_distance_correlation"])
    print("Robust Jensen-Shannon  Dependency Measure:", bootstrapped_similarity_stats_json["jensen_shannon_dependency_measure"])
    print("Robust Normalized Mutual Information:", bootstrapped_similarity_stats_json["normalized_mutual_information"])
    print("Robust Hoeffding's D:", bootstrapped_similarity_stats_json["hoeffding_d"])
    print("_______________________________________________________________________________________________________________________________________________\n")

    # Compute the differences between exact and bootstrapped results
    measures = ["spearman_rho", "kendall_tau", "approximate_distance_correlation", "jensen_shannon_dependency_measure", "normalized_mutual_information", "hoeffding_d"]
    for measure in measures:
        exact_value = similarity_stats_json[measure]
        bootstrapped_value = bootstrapped_similarity_stats_json[measure]
        absolute_difference = abs(exact_value - bootstrapped_value)
        percentage_difference = (absolute_difference / exact_value) * 100

        print(f"\nDifference between exact and bootstrapped {measure}: {absolute_difference}")
        print(f"Difference as % of the exact value: {percentage_difference:.2f}%")

    print("Now testing with a larger dataset, using sentence embedddings from Llama2 (4096-dimensional vectors) on some Shakespeare Sonnets...")
    # Load the embeddings into a DataFrame
    input_file_path = "sample_input_files/Shakespeare_Sonnets_small.json"
    embeddings_df = convert_embedding_json_to_pandas_df(input_file_path)

    # Select a random row for the query embedding
    query_embedding_index = choice(embeddings_df.index)
    query_embedding = embeddings_df.loc[query_embedding_index]
    print(f"Selected query embedding for sentence: `{query_embedding_index}`")

    # Remove the selected row from the DataFrame
    embeddings_df = embeddings_df.drop(index=query_embedding_index)

    # Apply the function to each row of embeddings_df
    json_outputs = embeddings_df.apply(lambda row: apply_fvs_to_vector(row, query_embedding), axis=1)

    # Create a DataFrame from the list of JSON outputs
    vector_similarity_results_df = pd.DataFrame.from_records(json_outputs)
    vector_similarity_results_df.index = embeddings_df.index

    # Add the required columns to the DataFrame
    columns = ["spearman_rho", "kendall_tau", "approximate_distance_correlation", "jensen_shannon_dependency_measure", "normalized_mutual_information", "hoeffding_d"]
    vector_similarity_results_df = vector_similarity_results_df[columns]

    # Sort the DataFrame by the hoeffding_d column in descending order
    vector_similarity_results_df = vector_similarity_results_df.sort_values(by="hoeffding_d", ascending=False)

    print("\nTop 10 most similar embedding results by Hoeffding's D:")
    print(vector_similarity_results_df.head(10))

if __name__ == "__main__":
    main()

Usage

In Rust

The core functions can be used directly within Rust projects. For example, use compute_vector_similarity_stats or compute_bootstrapped_similarity_stats with appropriate parameters for efficient computations.

In Python

Install the Python package and use the exposed functions to compute vector similarity or perform bootstrapped analysis, as demonstrated in the example above.


Detailed Overview of Similarity Measures

1. Spearman's Rank-Order Correlation (spearman_rho)

Spearman’s Rank-Order Correlation is a non-parametric measure of the strength and direction of the monotonic relationship between two variables. Unlike Pearson's correlation, which measures linear relationships, Spearman's correlation can capture non-linear monotonic relationships. This makes it useful in many real-world applications where variables have complex relationships but still follow a consistent directional trend.

How It Works: - First, both input vectors are converted into ranks, where the lowest value is assigned rank 1, the second-lowest rank 2, and so on. If ties are present, the average rank for the tied values is computed. - Once the ranks are assigned, the measure reduces to computing the Pearson correlation on these ranks. However, the key difference lies in its robustness to non-linearity.

Optimizations in Our Implementation: - Parallel Sorting: The library uses parallel sorting with the rayon crate to assign ranks, ensuring that this operation scales efficiently even for large datasets. - Efficient Rank Calculation: The average rank computation in the presence of ties is optimized with a direct look-up mechanism, minimizing redundant operations when processing multiple tied values in sequence.

Why It Stands Out: - Robust Against Outliers: Since it uses ranks rather than raw data values, Spearman's correlation is less sensitive to outliers. - Monotonic Relationships: It captures monotonic trends, making it suitable for many practical scenarios where linear correlation fails but directional trends exist.

2. Kendall's Tau Rank Correlation (kendall_tau)

Kendall’s Tau is a rank-based measure that evaluates the strength of ordinal association between two variables by comparing the relative ordering of data points. It is interpreted as the probabil

Core symbols most depended-on inside this repo

log_memory_usage
called by 18
benches/benchmark.rs
spearman_rho
called by 7
src/lib.rs
kendall_tau
called by 7
src/lib.rs
jensen_shannon_dependency_measure
called by 7
src/lib.rs
approximate_distance_correlation
called by 7
src/lib.rs
exact_hoeffdings_d_func
called by 7
src/lib.rs
normalized_mutual_information
called by 7
src/lib.rs
average_rank
called by 6
src/lib.rs

Shape

Function 29

Languages

Rust90%
Python10%

Modules by API surface

src/lib.rs20 symbols
benches/benchmark.rs6 symbols
python/vector_similarity_test.py3 symbols

For agents

$ claude mcp add fast_vector_similarity \
  -- python -m otcore.mcp_server <graph>

⬇ download graph artifact

Ask about this repo answers extend the page