Skip to content

Commit 9579d8f

Browse files
alibeklfcmeta-codesync[bot]
authored andcommitted
Add type stubs for SVS index classes + IndexIVFFlatPanorama.batch_size (#5489)
Summary: Pull Request resolved: #5489 Fbcode/faiss/python/__init__.pyi is missing type stubs for 7 SWIG-exposed SVS (Intel Scalable Vector Search) index classes and one field on IndexIVFFlatPanorama, causing Pyre `[missing-attribute]` errors for any Python caller that constructs or type-annotates these classes. `swigfaiss.swig` `%include`s and `DOWNCAST`s `IndexSVSFlat`, `IndexSVSVamana`, `IndexSVSVamanaLVQ`, `IndexSVSVamanaLeanVec`, `IndexSVSIVF`, `IndexSVSIVFLVQ`, and `IndexSVSIVFLeanVec` (lines 763-769, 928-934) -- all 7 classes are live, constructible Python types today. None of the 7 appear anywhere in `__init__.pyi`: 0 matches for each. Verified against current trunk before implementing, not from a stale backlog snapshot. This diff adds: - `SVSStorageKind = int` module-level type alias plus the 10 constant values (`SVS_FP32`, `SVS_FP16`, `SVS_SQ8`, `SVS_LVQ4x0/4x4/4x8`, `SVS_LVQ8x0`, `SVS_LeanVec4x4/4x8/8x8`, `SVS_count`), matching the existing `MetricType = int` / `METRIC_L2: int` convention used for every other plain (non-`enum class`) C++ enum in this file -- `SVSStorageKind` is declared as an unscoped `enum` in `svs/IndexSVSVamana.h`, so SWIG exposes its values as bare top-level names, not `SVSStorageKind_`-prefixed names (that prefix convention only applies to C++11 `enum class` types, e.g. `ClusteringInitMethod`). - `SearchParametersSVSVamana` and `SearchParametersSVSIVF` stubs (`search_window_size`/`search_buffer_capacity`, `n_probes`/`k_reorder` respectively), the two `SearchParameters` subclasses defined alongside the SVS index headers that were equally unstubbed. - `IndexSVSFlat`, `IndexSVSVamana` (+ `is_lvq_leanvec_enabled()` static method), `IndexSVSVamanaLVQ`, `IndexSVSVamanaLeanVec` (+ `train_with_queries` support surfaced via the base `Index.train()` Python wrapper, not a separate stub method -- see below), `IndexSVSIVF` (+ `is_lvq_leanvec_enabled()`), `IndexSVSIVFLVQ`, and `IndexSVSIVFLeanVec`, each with the constructor signature and public config fields read directly from their C++ headers (`svs/IndexSVS*.h`). Internal implementation-detail members (`impl`, `mmap_owner`, `stored_vectors`, `stored_vectors_valid`, `training_data` -- raw pointers into the unwrapped `svs_runtime::*` library, or reconstruction-cache storage) are deliberately excluded, matching this file's existing convention of omitting internal storage fields even when technically public (e.g. `IndexIVFFlatPanorama.cum_sums` is similarly excluded today). - `IndexIVFFlatPanorama.batch_size: int` field and constructor parameter (default `Panorama::kDefaultBatchSize` = 128, expressed as `= ...` per this file's existing convention for non-literal defaults). The class already had `n_levels` stubbed but was missing `batch_size`, added in the same commit (D111132644-era) as the class itself. Confirmed `train_with_queries` (a raw SWIG-exposed C++ method used internally by `Index`'s Python `train()` wrapper for out-of-distribution training data, per `class_wrappers.py`) does not need its own stub entry: the same pattern already excludes `train_c`/`train_ex`, the other two raw per-numeric-type dispatch targets of the same wrapper -- callers use `index.train(x, xq_train=...)`, not the raw method name directly. This is a stub-only change: `python/__init__.pyi` is consumed exclusively by static type checkers (Pyre, mypy, pyright) and IDE autocompletion, not by the Python runtime, so no behavior change is possible. Validated with `python3 -c "import ast; ast.parse(open('python/__init__.pyi').read())"` (0 syntax errors) and a full-file identifier-occurrence grep confirming each new symbol appears exactly where intended with no accidental duplicate class/constant definitions. `buck2 build fbcode//faiss:faiss` and `fbcode//faiss/python:pyfaiss` both build clean (0 warnings, 0 errors); `buck2 test fbcode//faiss/tests:test_io` (Friday rotation target) passes 30/30. ___ Differential Revision: D114349814 fbshipit-source-id: 4bfe5ad481438d1727247235240634a5a02a73b1
1 parent a3d59f0 commit 9579d8f

1 file changed

Lines changed: 126 additions & 0 deletions

File tree

faiss/python/__init__.pyi

Lines changed: 126 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -39,6 +39,20 @@ ClusteringInitMethod_RANDOM: int
3939
ClusteringInitMethod_KMEANS_PLUS_PLUS: int
4040
ClusteringInitMethod_AFK_MC2: int
4141

42+
# Storage kind for SVS (Intel Scalable Vector Search) indexes
43+
SVSStorageKind = int
44+
SVS_FP32: int
45+
SVS_FP16: int
46+
SVS_SQ8: int
47+
SVS_LVQ4x0: int
48+
SVS_LVQ4x4: int
49+
SVS_LVQ4x8: int
50+
SVS_LVQ8x0: int
51+
SVS_LeanVec4x4: int
52+
SVS_LeanVec4x8: int
53+
SVS_LeanVec8x8: int
54+
SVS_count: int
55+
4256
# I/O flag constants for reading/writing indexes
4357
IO_FLAG_SKIP_STORAGE: int # skip the storage for graph-based indexes
4458
IO_FLAG_READ_ONLY: int # read-only mode
@@ -277,6 +291,16 @@ class SearchParametersPreTransform(SearchParameters):
277291
index_params: SearchParameters | None
278292
def __init__(self) -> None: ...
279293

294+
class SearchParametersSVSVamana(SearchParameters):
295+
search_window_size: int
296+
search_buffer_capacity: int
297+
def __init__(self) -> None: ...
298+
299+
class SearchParametersSVSIVF(SearchParameters):
300+
n_probes: int
301+
k_reorder: float
302+
def __init__(self) -> None: ...
303+
280304
# Base Index class
281305
class Index:
282306
d: int # vector dimension
@@ -1803,6 +1827,7 @@ class IndexIVFFlatPanorama(IndexIVFFlat):
18031827
"""Panorama adaptation of IndexIVFFlat following https://arxiv.org/abs/2510.00566"""
18041828

18051829
n_levels: int
1830+
batch_size: int
18061831

18071832
def __init__(
18081833
self,
@@ -1812,6 +1837,7 @@ class IndexIVFFlatPanorama(IndexIVFFlat):
18121837
n_levels: int,
18131838
metric: MetricType = METRIC_L2,
18141839
own_invlists: bool = True,
1840+
batch_size: int = ...,
18151841
) -> None: ...
18161842

18171843
class IndexIVFPQ(IndexIVF):
@@ -3833,6 +3859,106 @@ class IndexIVFRaBitQFastScan(IndexIVFFastScan):
38333859
@overload
38343860
def __init__(self, orig: IndexIVFRaBitQ, bbs: int = 32) -> None: ...
38353861

3862+
# SVS (Intel Scalable Vector Search) indexes
3863+
class IndexSVSFlat(Index):
3864+
nlabels: int
3865+
def __init__(self, d: int, metric: MetricType = METRIC_L2) -> None: ...
3866+
3867+
class IndexSVSVamana(Index):
3868+
graph_max_degree: int
3869+
prune_to: int
3870+
alpha: float
3871+
search_window_size: int
3872+
search_buffer_capacity: int
3873+
construction_window_size: int
3874+
max_candidate_pool_size: int
3875+
use_full_search_history: bool
3876+
is_static: bool
3877+
storage_kind: SVSStorageKind
3878+
3879+
def __init__(
3880+
self,
3881+
d: int,
3882+
degree: int,
3883+
metric: MetricType = METRIC_L2,
3884+
storage: SVSStorageKind = SVS_FP32,
3885+
is_static: bool = False,
3886+
) -> None: ...
3887+
@staticmethod
3888+
def is_lvq_leanvec_enabled() -> bool: ...
3889+
3890+
class IndexSVSVamanaLVQ(IndexSVSVamana):
3891+
def __init__(
3892+
self,
3893+
d: int,
3894+
degree: int,
3895+
metric: MetricType = METRIC_L2,
3896+
storage: SVSStorageKind = SVS_LVQ4x0,
3897+
is_static: bool = False,
3898+
) -> None: ...
3899+
3900+
class IndexSVSVamanaLeanVec(IndexSVSVamana):
3901+
leanvec_d: int
3902+
3903+
def __init__(
3904+
self,
3905+
d: int,
3906+
degree: int,
3907+
metric: MetricType = METRIC_L2,
3908+
leanvec_dims: int = 0,
3909+
storage: SVSStorageKind = SVS_LeanVec4x4,
3910+
is_static: bool = False,
3911+
) -> None: ...
3912+
3913+
class IndexSVSIVF(Index):
3914+
num_centroids: int
3915+
minibatch_size: int
3916+
num_iterations: int
3917+
is_hierarchical: bool
3918+
training_fraction: float
3919+
hierarchical_level1_clusters: int
3920+
seed: int
3921+
n_probes: int
3922+
k_reorder: float
3923+
num_threads: int
3924+
intra_query_threads: int
3925+
is_static: bool
3926+
storage_kind: SVSStorageKind
3927+
3928+
def __init__(
3929+
self,
3930+
d: int,
3931+
nlist: int,
3932+
metric: MetricType = METRIC_L2,
3933+
storage: SVSStorageKind = SVS_FP32,
3934+
is_static: bool = False,
3935+
) -> None: ...
3936+
@staticmethod
3937+
def is_lvq_leanvec_enabled() -> bool: ...
3938+
3939+
class IndexSVSIVFLVQ(IndexSVSIVF):
3940+
def __init__(
3941+
self,
3942+
d: int,
3943+
nlist: int,
3944+
metric: MetricType = METRIC_L2,
3945+
storage: SVSStorageKind = SVS_LVQ4x0,
3946+
is_static: bool = False,
3947+
) -> None: ...
3948+
3949+
class IndexSVSIVFLeanVec(IndexSVSIVF):
3950+
leanvec_d: int
3951+
3952+
def __init__(
3953+
self,
3954+
d: int,
3955+
nlist: int,
3956+
metric: MetricType = METRIC_L2,
3957+
leanvec_dims: int = 0,
3958+
storage: SVSStorageKind = SVS_LeanVec4x4,
3959+
is_static: bool = False,
3960+
) -> None: ...
3961+
38363962
# Independent quantizer
38373963
class IndexIVFIndependentQuantizer(Index):
38383964
quantizer: Index

0 commit comments

Comments
 (0)