From 09b1bbc12ab8683dcf467d9cac63132aa71a37bf Mon Sep 17 00:00:00 2001 From: Will Jones Date: Fri, 5 Jun 2026 07:52:40 -0700 Subject: [PATCH] refactor!: drop unused loss field from IndexStatistics (#3496) MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit BREAKING CHANGE: direct Rust users lose the `IndexStatistics::loss` field. Python and Node.js consumers are unaffected in practice for remote tables (the value was always `None`/absent), but the attribute is gone for local tables too. `IndexStatistics::loss` was local-only — LanceDB Cloud never returned it, so `RemoteTable::index_stats` always set `loss: None`. It's vestigial; this removes it. - Remove `loss` from `IndexStatistics` and the internal `IndexMetadata` in `rust/lancedb/src/index.rs`, plus the summing logic in `NativeTable::index_stats`. - Drop `loss` from the Python and Node.js bindings (and their tests/docs). Fixes #3493 🤖 Generated with [Claude Code](https://claude.com/claude-code) --------- Co-authored-by: Claude Opus 4.8 (1M context) --- docs/src/js/interfaces/IndexStatistics.md | 11 ----------- nodejs/__test__/table.test.ts | 3 +-- nodejs/src/table.rs | 4 ---- python/python/lancedb/table.py | 3 --- python/python/tests/test_index.py | 2 -- python/src/table.rs | 4 ---- rust/lancedb/src/index.rs | 3 --- rust/lancedb/src/remote/table.rs | 1 - rust/lancedb/src/table.rs | 9 --------- 9 files changed, 1 insertion(+), 39 deletions(-) diff --git a/docs/src/js/interfaces/IndexStatistics.md b/docs/src/js/interfaces/IndexStatistics.md index e9abf7ade..3b1d8ccfc 100644 --- a/docs/src/js/interfaces/IndexStatistics.md +++ b/docs/src/js/interfaces/IndexStatistics.md @@ -30,17 +30,6 @@ The type of the index *** -### loss? - -```ts -optional loss: number; -``` - -The KMeans loss value of the index, -it is only present for vector indices. - -*** - ### numIndexedRows ```ts diff --git a/nodejs/__test__/table.test.ts b/nodejs/__test__/table.test.ts index 12fee4733..d87fa34d4 100644 --- a/nodejs/__test__/table.test.ts +++ b/nodejs/__test__/table.test.ts @@ -721,7 +721,7 @@ describe("When creating an index", () => { columns: ["vec"], }); const stats = await tbl.indexStats("vec_idx"); - expect(stats?.loss).toBeDefined(); + expect(stats).toBeDefined(); // Search without specifying the column let rst = await tbl @@ -1150,7 +1150,6 @@ describe("When creating an index", () => { expect(stats?.distanceType).toBeUndefined(); expect(stats?.indexType).toEqual("BTREE"); expect(stats?.numIndices).toEqual(1); - expect(stats?.loss).toBeUndefined(); }); test("when getting stats on non-existent index", async () => { diff --git a/nodejs/src/table.rs b/nodejs/src/table.rs index 2add2f3f3..5f8be3244 100644 --- a/nodejs/src/table.rs +++ b/nodejs/src/table.rs @@ -838,9 +838,6 @@ pub struct IndexStatistics { pub distance_type: Option, /// The number of parts this index is split into. pub num_indices: Option, - /// The KMeans loss value of the index, - /// it is only present for vector indices. - pub loss: Option, } impl From for IndexStatistics { fn from(value: lancedb::index::IndexStatistics) -> Self { @@ -850,7 +847,6 @@ impl From for IndexStatistics { index_type: value.index_type.to_string(), distance_type: value.distance_type.map(|d| d.to_string()), num_indices: value.num_indices, - loss: value.loss, } } } diff --git a/python/python/lancedb/table.py b/python/python/lancedb/table.py index 893023060..e6b48fdce 100644 --- a/python/python/lancedb/table.py +++ b/python/python/lancedb/table.py @@ -5637,8 +5637,6 @@ class IndexStatistics: The distance type used by the index. num_indices: Optional[int] The number of parts the index is split into. - loss: Optional[float] - The KMeans loss for the index, for only vector indices. """ num_indexed_rows: int @@ -5658,7 +5656,6 @@ class IndexStatistics: ] distance_type: Optional[Literal["l2", "cosine", "dot"]] = None num_indices: Optional[int] = None - loss: Optional[float] = None # This exists for backwards compatibility with an older API, which returned # a dictionary instead of a class. diff --git a/python/python/tests/test_index.py b/python/python/tests/test_index.py index 18b845b2b..cf342eb5c 100644 --- a/python/python/tests/test_index.py +++ b/python/python/tests/test_index.py @@ -226,7 +226,6 @@ async def test_create_vector_index(some_table: AsyncTable): assert stats.num_indexed_rows == await some_table.count_rows() assert stats.num_unindexed_rows == 0 assert stats.num_indices == 1 - assert stats.loss >= 0.0 @pytest.mark.asyncio @@ -250,7 +249,6 @@ async def test_create_4bit_ivfpq_index(some_table: AsyncTable): assert stats.num_indexed_rows == await some_table.count_rows() assert stats.num_unindexed_rows == 0 assert stats.num_indices == 1 - assert stats.loss >= 0.0 @pytest.mark.asyncio diff --git a/python/src/table.rs b/python/src/table.rs index dc5f5ec0c..ea98d447e 100644 --- a/python/src/table.rs +++ b/python/src/table.rs @@ -711,10 +711,6 @@ impl Table { dict.set_item("num_indices", num_indices)?; } - if let Some(loss) = stats.loss { - dict.set_item("loss", loss)?; - } - Ok(Some(dict.unbind())) }) } else { diff --git a/rust/lancedb/src/index.rs b/rust/lancedb/src/index.rs index 3a55eeedf..f7a53375b 100644 --- a/rust/lancedb/src/index.rs +++ b/rust/lancedb/src/index.rs @@ -372,7 +372,6 @@ pub(crate) struct IndexMetadata { pub metric_type: Option, // Sometimes the index type is provided at this level. pub index_type: Option, - pub loss: Option, } // This struct is used to deserialize the JSON data returned from the Lance API @@ -404,6 +403,4 @@ pub struct IndexStatistics { pub distance_type: Option, /// The number of parts this index is split into. pub num_indices: Option, - /// The loss value used by the index. - pub loss: Option, } diff --git a/rust/lancedb/src/remote/table.rs b/rust/lancedb/src/remote/table.rs index f894d1b68..fa1355254 100644 --- a/rust/lancedb/src/remote/table.rs +++ b/rust/lancedb/src/remote/table.rs @@ -4121,7 +4121,6 @@ mod tests { index_type: IndexType::IvfPq, distance_type: Some(DistanceType::L2), num_indices: None, - loss: None, }; assert_eq!(indices, expected); diff --git a/rust/lancedb/src/table.rs b/rust/lancedb/src/table.rs index 355483f0c..cdd8edfcf 100644 --- a/rust/lancedb/src/table.rs +++ b/rust/lancedb/src/table.rs @@ -3019,20 +3019,12 @@ impl BaseTable for NativeTable { .ok_or_else(|| Error::InvalidInput { message: "index statistics was missing index type".to_string(), })?; - let loss = stats - .indices - .iter() - .map(|index| index.loss.unwrap_or_default()) - .sum::(); - - let loss = first_index.loss.map(|first_loss| first_loss + loss); Ok(Some(IndexStatistics { num_indexed_rows: stats.num_indexed_rows, num_unindexed_rows: stats.num_unindexed_rows, index_type, distance_type: first_index.metric_type, num_indices: stats.num_indices, - loss, })) } @@ -3435,7 +3427,6 @@ mod tests { assert_eq!(stats.num_unindexed_rows, 0); assert_eq!(stats.index_type, crate::index::IndexType::IvfPq); assert_eq!(stats.distance_type, Some(crate::DistanceType::L2)); - assert!(stats.loss.is_some()); table.drop_index(index_name).await.unwrap(); assert_eq!(table.list_indices().await.unwrap().len(), 0);