Hora Search

Hora search everywhere!

Features

Portable 💼

  • Support WebAssembly
  • Support Windows, Linux and OS X
  • Support no_std (WIP, not all features)
  • Support IOS and Android (WIP)
  • No heavy dependency, such as BLAS

Reliable and Productive ⭐

  • Rust compiler secure all code
  • Memory managed by Rust for all language libs such as horapy
  • Broad testing coverage
  • Well documented
  • Elegant and simple API, easy to learn

Performant ⚡️

  • SIMD-Accelerated (packed_simd)
  • Stable algorithm implementation
  • Multiple threads design

Multiple Languages Support✨

Multiple Indexes Support 🚀

  • Hierarchical Navigable Small World Graph Index (HNSW)
  • Satellite System Graph (SSG)
  • Product Quantization Inverted File (PQIVF)
  • Random Projection Tree (RPT)
  • BruteForce (naive implementation with SIMD accelerated)

Multiple Distances Support 🧮

  • Dot Product Distance
  • Euclidean Distance
  • Manhattan Distance
  • Cosine Similarity

Installation

$ pip install horapy # recommend# or install from source$ git clone https://github.com/hora-search/horapy && cd horapy$ pip install maturin && maturin build --release

Demos

Choose one celebrity below…

all image data comes from [CelebA dataset], we use it only for algorithm demo, not any commercial activity.

Benchmark

benchmark

by a AWS t2.medium (CPU: Intel(R) Xeon(R) CPU E5-2686 v4 @ 2.30GHz) [more]

Examples

import numpy as npfrom horapy import HNSWIndexdimension = 50n = 1000# init index instanceindex = HNSWIndex(dimension, "usize")samples = np.float32(np.random.rand(n, dimension))for i in range(0, len(samples)):    # add node    index.add(np.float32(samples[i]), i)index.build("euclidean")  # build indextarget = np.random.randint(0, n)# 410 in Hora ANNIndex <HNSWIndexUsize> (dimension: 50, dtype: usize, max_item: 1000000, n_neigh: 32, n_neigh0: 64, ef_build: 20, ef_search: 500, has_deletion: False)# has neighbors: [410, 736, 65, 36, 631, 83, 111, 254, 990, 161]print("{} in {} has neighbors: {}".format(    target, index, index.search(samples[target], 10)))  # search