Add Int8Rescored: int8 graph walk with exact float re-ranking - #31
Merged
Merged
Conversation
An int8 file may now also carry the original floats as an optional (non-Required) Vectors section in slot 8, flagged with HasOptionalSections. QuantizationMode stays 2, so a reader that predates this change opens the file as plain int8. The API reports VectorQuantization.Int8Rescored when the section is present. The graph is built and walked on the int8 codes exactly as before; the ef candidates from the bottom layer are then re-ranked against the floats, so returned scores and top-k are the float ones. Exhaustive paths (SearchSimple, SearchSimpleParallel, the filtered fallback, Rerank) score on floats directly, and GetByGuid returns the original vector. Grow, Update, Delete and Vacuum keep both sections in step because every write goes through WriteVectorToDisk. Benchmark: --quantization int8rescored. Co-authored-by: Copilot App <223556219+Copilot@users.noreply.github.com>
Cohere 1M (12 threads, k=100, M=15): rescored reaches float recall@100 at efSearch 180 and 320 (94.7 / 97.4 %) at 6,778 / 3,884 QPS, against float 3,764 / 2,207 and int8 6,841 / 4,714. Build 170 s vs 419 s float; file 4,124 MiB. No recall gain when efSearch == k, stated as such. Co-authored-by: Copilot App <223556219+Copilot@users.noreply.github.com>
This file contains hidden or bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
Sign up for free
to join this conversation on GitHub.
Already have an account?
Sign in to comment
Add this suggestion to a batch that can be applied as a single commit.This suggestion is invalid because no changes were made to the code.Suggestions cannot be applied while the pull request is closed.Suggestions cannot be applied while viewing a subset of changes.Only one suggestion per line can be applied in a batch.Add this suggestion to a batch that can be applied as a single commit.Applying suggestions on deleted lines is not supported.You must change the existing code in this line in order to create a valid suggestion.Outdated suggestions cannot be applied.This suggestion has been applied or marked resolved.Suggestions cannot be applied from pending reviews.Suggestions cannot be applied on multi-line comments.Suggestions cannot be applied while the pull request is queued to merge.Suggestion cannot be applied right now. Please check back later.
Summary
Adds
VectorQuantization.Int8Rescored: the HNSW graph is built and walked on int8 codes exactly as inInt8, but the original floats are kept in the file and theefSearchcandidates are re-ranked against them. Returned scores and top-k are the float ones;GetByGuidreturns the original vector.This is the "float refiner" the Cohere 1M benchmark write-up identified as the remaining lever, and the equivalent of zvec's
--is-using-refiner.Format
No version bump, no new
QuantizationMode. A rescored file is an int8 file (QuantizationMode = 2) that additionally carries section 1 (Vectors) as an optional, non-Required section in slot 8, withHasOptionalSectionsset. Readers that predate this change open it as plain int8.QvecDatabase.QuantizationreportsInt8Rescoredwhen the section is present; reopening with the wrong mode throws in both directions. Header validation checks the float section's shape when present. Float and plain int8 files are unchanged (existing tests pass untouched).Implementation
_vectorSectionOffsetsplit into_floatVectorSectionOffset/_codesSectionOffset;_rescoreflag.WriteVectorToDiskwrites codes + params and, when rescored, the floats too — soAddEntry,AddEntries,UpdateVectorandVacuumall keep both sections in step.ReadVectorIntoreturns the exact floats when available.FinalScore/RescoreCandidates: exact float scoring afterSearchLayerNearest/SearchLayerFiltered, and in every exhaustive path. No-ops for float and int8 files.--quantization int8rescored.Tests
RescoredQuantizationTests(16): layout,Openreports the mode, mismatch both ways, exactGetByGuid, scores equal float brute force (1e-4) in all three metrics, recall >= 97 % on tight cosine clusters where int8 alone measured 89.8 %, filtered search, Update/Delete/Vacuum, Grow, parallelAddEntries. Fast suite + Slow suite green, 0 warnings.Measurements (Cohere 1M, 768-d cosine, k=100, M=15, 12 threads)
Float recall at int8 throughput, paid for in storage (~1.25x float). Honest caveat, in the docs: at
efSearch == kre-ranking cannot add candidates, so the ef 100 row stays at int8 recall (89.2 %). Float/int8 indexes re-queried the same day were within 6 % of the table.siftsmall: rescored 99.1 / 99.8 % recall@10 at ef 20 / 80 vs float 98.6 / 99.5 and int8 98.3 / 99.0.
Docs
docs/design-quantization-rescoring.md(new),docs/design-quantization-int8.md,docs/design-format-v4.md,benchmarks/README.md,README.md.