leaves12138 commented on code in PR #61:
URL: 
https://github.com/apache/paimon-vector-index/pull/61#discussion_r3629927505


##########
docs/api.html:
##########
@@ -0,0 +1,273 @@
+<!--
+  Licensed to the Apache Software Foundation (ASF) under one or more
+  contributor license agreements. See the NOTICE file distributed with
+  this work for additional information regarding copyright ownership.
+  The ASF licenses this file to you under the Apache License, Version 2.0.
+-->
+<!doctype html>
+<html lang="en">
+<head>
+  <meta charset="utf-8">
+  <meta name="viewport" content="width=device-width, initial-scale=1">
+  <meta name="description" content="Unified Paimon Vector Index APIs for Rust, 
C, C++, Java, and Python, including warm-up and metadata filter pushdown.">
+  <title>API and Language Bindings · Paimon Vector Index</title>
+  <link rel="stylesheet" href="styles.css">
+  <script src="docs.js" defer></script>
+</head>
+<body>
+  <a class="skip-link" href="#main">Skip to content</a>
+  <header class="site-header"><div class="header-inner">
+    <a class="brand" href="index.html" aria-label="Paimon Vector Index 
documentation home"><span class="brand-mark">VI</span><span>Paimon Vector 
Index</span></a>
+    <nav class="site-nav" data-site-nav aria-label="Documentation"><a 
href="index.html">Overview</a><a href="api.html" aria-current="page">API</a><a 
href="development.html">Development</a><a href="ivf-flat.html">IVF-FLAT</a><a 
href="ivf-pq.html">IVF-PQ</a><a href="ivf-rq.html">IVF-RQ</a><a 
href="ivf-hnsw-flat.html">HNSW-FLAT</a><a 
href="ivf-hnsw-sq.html">HNSW-SQ</a></nav>
+    <div class="header-actions"><button class="icon-button" type="button" 
data-theme-toggle aria-label="Switch color theme">◐</button><button 
class="nav-toggle" type="button" data-nav-toggle aria-expanded="false" 
aria-label="Open navigation">☰</button></div>
+  </div></header>
+
+  <main id="main"><div class="page-shell">
+    <section class="hero detail-hero">
+      <p class="eyebrow">One lifecycle · five language surfaces</p>
+      <h1>API and language bindings</h1>
+      <p class="hero-lead">The Rust core, C FFI, C++ RAII layer, Java/JNI, and 
Python ctypes package share one train → write → serialize → detect → search 
model. Build options select the index type; Readers discover it from the file 
magic.</p>
+      <div class="badge-row"><span class="badge strong">Unified 
lifecycle</span><span class="badge">Positional I/O</span><span 
class="badge">Single and batch search</span><span class="badge">Roaring64 
prefilter</span></div>
+    </section>
+
+    <div class="doc-layout">
+      <aside class="toc" aria-label="On this page"><strong>On this 
page</strong><a href="#workspace">Modules</a><a 
href="#lifecycle">Lifecycle</a><a href="#params">Search parameters</a><a 
href="#warmup">Warm-up</a><a href="#rust">Rust</a><a href="#c">C FFI</a><a 
href="#cpp">C++</a><a href="#java">Java/JNI</a><a href="#python">Python</a><a 
href="#filter">Filter pushdown</a></aside>
+      <article class="article">
+        <section class="article-section" id="workspace">
+          <h2>Public integration layers</h2>
+          <div 
class="table-wrap"><table><thead><tr><th>Module</th><th>Role</th><th>Primary 
entry point</th></tr></thead><tbody>
+            <tr><td><code>core</code></td><td>Pure Rust indexes, file 
Readers/Writers, and 
benchmarks</td><td><code>paimon_vindex_core::index</code></td></tr>
+            <tr><td><code>ffi</code></td><td>C ABI over the Rust core; builds 
<code>libpaimon_vindex_ffi</code></td><td>Generated 
<code>include/paimon_vindex.h</code></td></tr>
+            <tr><td><code>include</code></td><td>C++ RAII 
wrapper</td><td><code>paimon_vindex.hpp</code></td></tr>
+            <tr><td><code>jni</code> + <code>java</code></td><td>JNI 
implementation and Java 
API</td><td><code>org.apache.paimon.index.vector</code></td></tr>
+            <tr><td><code>python</code></td><td>Pure Python package loading 
the C FFI through ctypes</td><td><code>paimon_vindex</code></td></tr>
+          </tbody></table></div>
+          <p>The top-level Cargo workspace contains <code>core</code>, 
<code>ffi</code>, and <code>jni</code>. The Python package loads the shared FFI 
library at runtime.</p>
+        </section>
+
+        <section class="article-section" id="lifecycle">
+          <h2>Shared lifecycle</h2>
+          <div class="flow" aria-label="Unified API lifecycle"><div 
class="flow-step"><small>01</small><strong>Create a Trainer<br>Parse and 
validate options</strong></div><div 
class="flow-step"><small>02</small><strong>Submit one or more<br>training 
batches</strong></div><div class="flow-step"><small>03</small><strong>Finish 
training and<br>create a one-shot Writer</strong></div><div 
class="flow-step"><small>04</small><strong>Add row IDs / vectors<br>and write 
the file</strong></div><div class="flow-step"><small>05</small><strong>Detect 
file magic<br>and execute searches</strong></div></div>
+          <ul><li>Vectors are contiguous <code>f32</code> values; length must 
equal <code>vector_count × dimension</code>.</li><li>Training data may arrive 
in batches, but the Trainer accumulates the full set. Batching avoids oversized 
language-level arrays; it does not reduce native peak memory.</li><li>A Writer 
may receive production vectors in multiple batches. Row-ID count must equal 
vector count.</li><li>Readers expose metadata, single-query search, batch 
search, and Roaring64-filtered variants.</li><li>Files carry their type and 
model sections. Callers do not pass index options again when opening a 
Reader.</li></ul>
+        </section>
+
+        <section class="article-section" id="params">
+          <h2>Shared search parameters</h2>
+          <div 
class="table-wrap"><table><thead><tr><th>Parameter</th><th>Applies 
to</th><th>Description</th></tr></thead><tbody>
+            <tr><td><code>top_k</code></td><td>All indexes</td><td>Number of 
nearest neighbors returned for each query.</td></tr>
+            <tr><td><code>nprobe</code></td><td>All indexes</td><td>Number of 
IVF lists probed. Larger values usually improve recall while increasing I/O and 
compute.</td></tr>
+            <tr><td><code>ef_search</code></td><td>IVF-HNSW-FLAT / 
SQ</td><td>Per-list graph-search breadth. <code>0</code> resolves to 
<code>max(top_k, 32)</code>.</td></tr>
+            <tr><td><code>query_bits</code></td><td>IVF-RQ 
only</td><td><code>0</code> keeps the float-query byte-LUT path; <code>4</code> 
/ <code>8</code> use quantized-query bit-plane scans.</td></tr>
+          </tbody></table></div>
+          <div class="callout warning"><strong>Stored RQ bits and query bits 
are different</strong>IVF-RQ currently writes 1-bit vector codes. 
<code>query_bits</code> is a per-request query quantization setting. Current 
Readers reject reserved multi-bit file payloads.</div>
+        </section>
+
+        <section class="article-section" id="warmup">
+          <h2>Search warm-up</h2>
+          <p>After opening a Reader and before repeated searches, call the 
language-specific warm-up method. It builds process-local caches without 
changing the file or results.</p>
+          <div 
class="table-wrap"><table><thead><tr><th>Language</th><th>Method</th><th>Current
 behavior</th></tr></thead><tbody>
+            <tr><td>Rust</td><td><code>optimize_for_search</code></td><td 
rowspan="5">IVF-PQ builds residual-L2 precomputed tables. IVF-HNSW-SQ builds SQ 
decode LUTs for filtered scans and fallback. Other indexes primarily preload 
metadata.</td></tr>
+            
<tr><td>C</td><td><code>paimon_vindex_reader_optimize_for_search</code></td></tr><tr><td>C++</td><td><code>optimize_for_search</code></td></tr><tr><td>Java</td><td><code>optimizeForSearch</code></td></tr><tr><td>Python</td><td><code>optimize_for_search</code></td></tr>
+          </tbody></table></div>
+          <p>The IVF-HNSW-SQ LUT is not used by normal unfiltered graph 
traversal, so warm-up is not expected to accelerate that path.</p>
+        </section>
+
+        <section class="article-section" id="rust">
+          <h2>Rust</h2>
+          <div class="code-block"><span class="code-label">Rust · train, 
write, and search</span><pre><code>use std::fs::File;
+
+use paimon_vindex_core::distance::MetricType;
+use paimon_vindex_core::hnsw::HnswBuildParams;
+use paimon_vindex_core::index::{
+    VectorIndexConfig, VectorIndexReader, VectorIndexTrainer,
+    VectorIndexWriter, VectorSearchParams,
+};
+use paimon_vindex_core::io::PosWriter;
+
+let config = VectorIndexConfig::IvfHnswSq {
+    dimension: 128,
+    nlist: 1024,
+    metric: MetricType::L2,
+    hnsw: HnswBuildParams::default(),
+};
+
+let training = VectorIndexTrainer::train(
+    config, &amp;training_vectors, training_count)?;
+let mut writer = VectorIndexWriter::new(training);
+writer.add_vectors(&amp;row_ids, &amp;vectors, vector_count)?;
+
+let mut file = File::create("vectors.pvindex")?;
+let mut out = PosWriter::new(&amp;mut file);
+writer.write(&amp;mut out)?;
+
+let file = File::open("vectors.pvindex")?;
+let mut reader = VectorIndexReader::open(file)?;
+reader.optimize_for_search()?;
+let params = VectorSearchParams::with_ef_search(10, 16, 80);
+let (ids, distances) = reader.search(&amp;query, params)?;</code></pre></div>
+          <div class="code-block"><span class="code-label">Rust · other 
configurations</span><pre><code>VectorIndexConfig::IvfFlat {
+    dimension: 128, nlist: 1024, metric: MetricType::L2,
+};
+VectorIndexConfig::IvfPq {
+    dimension: 128, nlist: 1024, m: 16,
+    metric: MetricType::L2, use_opq: false,
+};
+VectorIndexConfig::IvfRq {
+    dimension: 128, nlist: 1024, metric: MetricType::L2,
+};
+VectorIndexConfig::IvfHnswFlat {
+    dimension: 128, nlist: 1024, metric: MetricType::L2,
+    hnsw: HnswBuildParams::default(),
+};</code></pre></div>
+        </section>
+
+        <section class="article-section" id="c">
+          <h2>C FFI</h2>
+          <p>The C ABI builds <code>libpaimon_vindex_ffi</code>; cbindgen 
produces the public header. Functions return <code>0</code> on success and 
<code>-1</code> on failure. <code>paimon_vindex_last_error()</code> exposes a 
thread-local error string.</p>

Review Comment:
   The `0`/`-1` convention only applies to status-returning operations. 
`paimon_vindex_trainer_open`, `paimon_vindex_trainer_finish`, 
`paimon_vindex_writer_open`, and `paimon_vindex_reader_open` return a handle or 
null; the free functions return `void`; and `paimon_vindex_last_error()` 
returns a string pointer. Could we describe the status-returning and 
handle-returning conventions separately?



##########
docs/development.html:
##########
@@ -0,0 +1,126 @@
+<!--
+  Licensed to the Apache Software Foundation (ASF) under one or more
+  contributor license agreements. See the NOTICE file distributed with
+  this work for additional information regarding copyright ownership.
+  The ASF licenses this file to you under the Apache License, Version 2.0.
+-->
+<!doctype html>
+<html lang="en">
+<head>
+  <meta charset="utf-8">
+  <meta name="viewport" content="width=device-width, initial-scale=1">
+  <meta name="description" content="Paimon Vector Index repository layout, 
development checks, cross-language tests, and ANN benchmarks.">
+  <title>Development and Benchmarks · Paimon Vector Index</title>
+  <link rel="stylesheet" href="styles.css">
+  <script src="docs.js" defer></script>
+</head>
+<body>
+  <a class="skip-link" href="#main">Skip to content</a>
+  <header class="site-header"><div class="header-inner">
+    <a class="brand" href="index.html" aria-label="Paimon Vector Index 
documentation home"><span class="brand-mark">VI</span><span>Paimon Vector 
Index</span></a>
+    <nav class="site-nav" data-site-nav aria-label="Documentation"><a 
href="index.html">Overview</a><a href="api.html">API</a><a 
href="development.html" aria-current="page">Development</a><a 
href="ivf-flat.html">IVF-FLAT</a><a href="ivf-pq.html">IVF-PQ</a><a 
href="ivf-rq.html">IVF-RQ</a><a href="ivf-hnsw-flat.html">HNSW-FLAT</a><a 
href="ivf-hnsw-sq.html">HNSW-SQ</a></nav>
+    <div class="header-actions"><button class="icon-button" type="button" 
data-theme-toggle aria-label="Switch color theme">◐</button><button 
class="nav-toggle" type="button" data-nav-toggle aria-expanded="false" 
aria-label="Open navigation">☰</button></div>
+  </div></header>
+
+  <main id="main"><div class="page-shell">
+    <section class="hero detail-hero"><p class="eyebrow">Build · test · 
measure</p><h1>Development and benchmarks</h1><p class="hero-lead">Run the 
standard Rust checks, exercise the C/C++, Java, and Python integrations, and 
measure ANN and filtered-query behavior with reproducible workloads.</p><div 
class="badge-row"><span class="badge strong">Cargo workspace</span><span 
class="badge">CMake smoke tests</span><span class="badge">Maven / 
pytest</span><span class="badge">Criterion benchmarks</span></div></section>
+
+    <div class="doc-layout">
+      <aside class="toc" aria-label="On this page"><strong>On this 
page</strong><a href="#workspace">Repository layout</a><a href="#rust">Rust 
checks</a><a href="#ann">ANN benchmark</a><a href="#filter-bench">Filter 
benchmark</a><a href="#c">C FFI</a><a href="#cpp">C++</a><a 
href="#java">Java/JNI</a><a href="#python">Python</a><a href="#format">Format 
compatibility</a></aside>
+      <article class="article">
+        <section class="article-section" id="workspace">
+          <h2>Repository layout</h2>
+          <div 
class="table-wrap"><table><thead><tr><th>Directory</th><th>Contents</th><th>Primary
 verification</th></tr></thead><tbody>
+            <tr><td><code>core/</code></td><td>Indexes, quantizers, HNSW, I/O, 
format fixtures, and benchmarks</td><td><code>cargo test -p 
paimon-vindex-core</code></td></tr>
+            <tr><td><code>ffi/</code></td><td>C ABI and shared 
library</td><td>C smoke test</td></tr>
+            <tr><td><code>include/</code></td><td>C++ RAII header</td><td>C++ 
smoke test</td></tr>
+            <tr><td><code>jni/</code></td><td>Rust JNI bridge</td><td>Java 
Maven tests</td></tr>
+            <tr><td><code>java/</code></td><td>Java public API and 
tests</td><td><code>mvn test</code></td></tr>
+            <tr><td><code>python/</code></td><td>ctypes package and pytest 
suite</td><td><code>pytest</code></td></tr>
+            <tr><td><code>c/</code> / <code>cpp/</code></td><td>Integration 
smoke-test projects</td><td>CMake</td></tr>
+            <tr><td><code>docs/</code></td><td>Index, API, and development 
documentation</td><td>Static link and structure checks</td></tr>
+          </tbody></table></div>
+        </section>
+
+        <section class="article-section" id="rust">
+          <h2>Standard Rust checks</h2>
+          <div class="code-block"><span 
class="code-label">Shell</span><pre><code>cargo fmt --all
+cargo test --workspace
+cargo clippy --workspace --all-targets</code></pre></div>
+          <p>Before submitting a change, keep formatting, workspace tests, and 
Clippy across all targets clean. Changes to binary layouts should also run the 
core storage-format fixtures.</p>
+        </section>
+
+        <section class="article-section" id="ann">
+          <h2>ANN benchmark</h2>
+          <p><code>ann_bench</code> compares IVF-PQ, IVF-RQ, IVF-HNSW-FLAT, 
and IVF-HNSW-SQ under one workload. It reports build time, Reader open/load 
time, first-query latency, batch throughput, and serialized index size.</p>
+          <div class="code-block"><span class="code-label">Shell · 
defaults</span><pre><code>cargo bench -p paimon-vindex-core --bench ann_bench 
-- --nocapture</code></pre></div>
+          <div class="code-block"><span class="code-label">Shell · explicit 
workload</span><pre><code>ANN_N=100000 ANN_NQ=1000 ANN_D=128 ANN_K=10 \
+ANN_NLIST=256 ANN_NPROBE=16 ANN_PQ_M=16 \
+ANN_HNSW_M=20 ANN_HNSW_EF_CONSTRUCTION=150 \
+ANN_HNSW_EF_SEARCH=80 ANN_RQ_QUERY_BITS=0 \
+cargo bench -p paimon-vindex-core --bench ann_bench -- 
--nocapture</code></pre></div>
+          <div 
class="table-wrap"><table><thead><tr><th>Variable</th><th>Meaning</th></tr></thead><tbody><tr><td><code>ANN_N
 / ANN_NQ</code></td><td>Indexed vector count / query 
count</td></tr><tr><td><code>ANN_D / ANN_K</code></td><td>Dimension / top 
K</td></tr><tr><td><code>ANN_NLIST / ANN_NPROBE</code></td><td>IVF list count / 
probed lists</td></tr><tr><td><code>ANN_PQ_M</code></td><td>IVF-PQ subquantizer 
count</td></tr><tr><td><code>ANN_HNSW_*</code></td><td>HNSW build and query 
parameters</td></tr><tr><td><code>ANN_RQ_QUERY_BITS</code></td><td>IVF-RQ query 
quantization: 0 / 4 / 8</td></tr></tbody></table></div>
+          <p><code>disk_scope=index_bytes</code> means the serialized 
vector-index file itself, excluding the outer Paimon file and manifest.</p>
+        </section>
+
+        <section class="article-section" id="filter-bench">
+          <h2>IVF-HNSW-SQ filter benchmark</h2>
+          <p>The filter-heavy benchmark measures batch filtered search before 
and after warm-up and verifies that both paths return identical results. It 
isolates the SQ decode LUT used by scan and fallback paths.</p>
+          <div class="code-block"><span class="code-label">Shell · 
defaults</span><pre><code>cargo bench -p paimon-vindex-core \
+  --bench ivfhnswsq_filter_bench -- --nocapture</code></pre></div>
+          <div class="code-block"><span class="code-label">Shell · explicit 
workload</span><pre><code>FILTER_BENCH_N=50000 FILTER_BENCH_NQ=500 
FILTER_BENCH_D=128 \
+FILTER_BENCH_NLIST=64 FILTER_BENCH_NPROBE=32 \
+FILTER_BENCH_EF_SEARCH=80 FILTER_BENCH_FILTER_STRIDES=1,4,16,64 \
+cargo bench -p paimon-vindex-core \
+  --bench ivfhnswsq_filter_bench -- --nocapture</code></pre></div>
+          <p><code>FILTER_BENCH_FILTER_STRIDES</code> simulates different 
selectivities through row-ID strides. Analyze direct scans, graph search, and 
insufficient-result backfill separately.</p>
+        </section>
+
+        <section class="article-section" id="c">
+          <h2>C FFI smoke test</h2>
+          <p>Build the release shared library, then compile the C test against 
the generated header.</p>
+          <div class="code-block"><span 
class="code-label">Shell</span><pre><code>cargo build --release -p 
paimon-vindex-ffi
+cmake -S c -B c/build
+cmake --build c/build
+LD_LIBRARY_PATH=target/release c/build/test_vindex</code></pre></div>
+          <div class="callout"><strong>Platform 
note</strong><code>LD_LIBRARY_PATH</code> is the Linux loader variable. Use the 
equivalent loader configuration on other platforms.</div>
+        </section>
+
+        <section class="article-section" id="cpp">
+          <h2>C++ smoke test</h2>
+          <p>The C++ test reuses the same FFI shared library and validates the 
RAII header.</p>
+          <div class="code-block"><span 
class="code-label">Shell</span><pre><code>cargo build --release -p 
paimon-vindex-ffi
+cmake -S cpp -B cpp/build
+cmake --build cpp/build
+LD_LIBRARY_PATH=target/release cpp/build/test_vindex_cpp</code></pre></div>
+        </section>
+
+        <section class="article-section" id="java">
+          <h2>Java / JNI tests</h2>
+          <p>Run the Java API tests from the JNI Java module:</p>
+          <div class="code-block"><span 
class="code-label">Shell</span><pre><code>mvn -f java/pom.xml 
test</code></pre></div>
+          <p>The suite covers option validation, Reader/Writer lifecycle, 
native panic boundaries, handle safety, metadata, single and batch search, and 
filter overloads.</p>

Review Comment:
   `mvn -f java/pom.xml test` only runs `VectorIndexJavaApiTest` through the 
Maven exec plugin. The native validation, panic-boundary, and handle-safety 
classes are standalone `main` programs that CI runs only after building 
`paimon-vindex-jni`. Please either include those build/run commands here or 
narrow this coverage claim to what the documented Maven command actually 
executes.



##########
README.md:
##########
@@ -23,436 +23,48 @@
 [actions]: 
https://github.com/apache/paimon-vector-index/actions?query=branch%3Amain
 
 Apache Paimon Vector Index is a pure Rust vector indexing library designed for
-Apache Paimon and data lake storage such as S3, HDFS, and OSS. Index readers 
use
-seek-based positional I/O so query execution can read only the parts of an 
index
-file needed by the selected IVF lists.
+Apache Paimon and data lake storage such as S3, HDFS, and OSS. Its seek-based
+readers load only the IVF lists selected by a query.
 
-The project is no longer limited to IVF-PQ. The unified writer and reader APIs
-support multiple index families across Rust, C FFI, Java/JNI, and Python:
+The library supports IVF-FLAT, IVF-PQ, IVF-RQ, IVF-HNSW-FLAT, and
+IVF-HNSW-SQ through shared Rust, C, C++, Java/JNI, and Python APIs.
 
-| Index type | Summary | Best fit |
-| --- | --- | --- |
-| `IVF_FLAT` | IVF partitioning with uncompressed vectors. | Baseline recall 
and simple storage. |
-| `IVF_PQ` | IVF with product quantization and optional OPQ rotation. | 
Compact indexes with fast approximate scans. |
-| `IVF_RQ` | IVF with 1-bit RaBitQ-style rotated residual quantization. | Very 
compact high-dimensional indexes with low training cost. |
-| `IVF_HNSW_FLAT` | IVF partitioning with an HNSW graph inside each list over 
raw vectors. | Higher recall within probed IVF lists. |
-| `IVF_HNSW_SQ` | IVF partitioning with per-list HNSW and scalar-quantized 
vectors. | HNSW-style search with smaller vector storage. |
+## Documentation
 
-All index types share:
+- [Index selection and architecture](docs/index.html): compare all index

Review Comment:
   These links currently open GitHub blob views, where the committed HTML is 
shown as source rather than as the styled site. I also could not find a Pages 
workflow, Pages configuration, or an `asf-site` branch in this repository. 
Since this PR removes most of the user-facing README content in favor of these 
pages, could we either publish `docs/` and link to the deployed URL, document a 
usable preview path, or keep the entry-point documentation in Markdown?



-- 
This is an automated message from the Apache Git Service.
To respond to the message, please log on to GitHub and use the
URL above to go to the specific comment.

To unsubscribe, e-mail: [email protected]

For queries about this service, please contact Infrastructure at:
[email protected]

Reply via email to