searchVectorsnow rejectsNaNand out-of-rangetopKandrerankFactorvalues with a clear error instead of producing undefined behaviorwriteVectorsskips auto-enabling binary quantization when the sign-bit codes are degenerate, avoiding a useless binary column that would hurt rather than help recall
- Search results are now deterministic: ties on score are broken by row index, so repeated queries return the same ordering
- Lower the default cluster
probecap from 96 to 48 lists; an explicitprobestill bypasses the cap
searchVectorsaccepts arrays forsource,metadata, andbinaryto query across multiple parquet files in one call; results are heap-merged into a global top-K and each carries asourceIndex. Single-source callers are unchangedwriteVectorsauto-tunesbinaryandclustersfrom the input size: binary turns on at N >= 10000 andclustersdefaults to round(sqrt(N)/2) when both are left unset. Passing either flag explicitly opts out of that knob's auto behaviornormalizenow defaults totrueinwriteVectors. Cosine on normalized vectors reduces to dot product; passnormalize: falseto opt out for magnitude-sensitive dot/euclidean metricswriteVectorsgains a streaming path: whenbinaryis set and clustering is off, it flushes one row group at a time, lowering peak memory from O(N) to O(row group)- The default cluster
probeis capped at 96 lists so the probed-list count stops growing with N once recall saturates; an explicitprobebypasses the cap - Fix clustered binary (Hamming) scan that could throw a RangeError or score the wrong bytes when a cluster's rows span multiple parquet pages
- Drop the redundant
hypvector.countKV metadata; readers take the count from the parquet footer's row count
- Add
prefetchBinaryto load the binary column into memory once at startup; pass the result asbinarytosearchVectorsto skip phase-1 fetches on every subsequent query - When clustering is enabled, write one parquet row group per cluster so phase-1 binary scans and phase-2 candidate fetches stay within a single column chunk per cluster
- Initial release