Compare commits

..

2 Commits

Author SHA1 Message Date
Lu Qiu a65db7038e build: point lance dependencies at the sibling submodule checkout
Path deps replace the git+tag pins so the sophon build resolves lance
from src/lance directly, independent of the pinned tag's version.
2026-07-24 14:38:19 -07:00
lancedb automation ea133edfca chore: update lance dependency to v10.0.0-beta.2 2026-07-23 21:25:42 +00:00
23 changed files with 98 additions and 292 deletions
Generated
+42 -42
View File
@@ -3421,8 +3421,8 @@ checksum = "42703706b716c37f96a77aea830392ad231f44c9e9a67872fa5548707e11b11c"
[[package]] [[package]]
name = "fsst" name = "fsst"
version = "10.0.0-beta.3" version = "10.0.0-beta.2"
source = "git+https://github.com/lance-format/lance.git?tag=v10.0.0-beta.3#ed078e7c19c9560906e1eae54b0baf01dc509986" source = "git+https://github.com/lance-format/lance.git?tag=v10.0.0-beta.2#bbc04776fff39355a7287e6feacb0041395a45e1"
dependencies = [ dependencies = [
"arrow-array", "arrow-array",
"rand 0.9.5", "rand 0.9.5",
@@ -4777,8 +4777,8 @@ checksum = "e037a2e1d8d5fdbd49b16a4ea09d5d6401c1f29eca5ff29d03d3824dba16256a"
[[package]] [[package]]
name = "lance" name = "lance"
version = "10.0.0-beta.3" version = "10.0.0-beta.2"
source = "git+https://github.com/lance-format/lance.git?tag=v10.0.0-beta.3#ed078e7c19c9560906e1eae54b0baf01dc509986" source = "git+https://github.com/lance-format/lance.git?tag=v10.0.0-beta.2#bbc04776fff39355a7287e6feacb0041395a45e1"
dependencies = [ dependencies = [
"arc-swap", "arc-swap",
"arrow", "arrow",
@@ -4852,8 +4852,8 @@ dependencies = [
[[package]] [[package]]
name = "lance-arrow" name = "lance-arrow"
version = "10.0.0-beta.3" version = "10.0.0-beta.2"
source = "git+https://github.com/lance-format/lance.git?tag=v10.0.0-beta.3#ed078e7c19c9560906e1eae54b0baf01dc509986" source = "git+https://github.com/lance-format/lance.git?tag=v10.0.0-beta.2#bbc04776fff39355a7287e6feacb0041395a45e1"
dependencies = [ dependencies = [
"arrow-array", "arrow-array",
"arrow-buffer", "arrow-buffer",
@@ -4875,7 +4875,7 @@ dependencies = [
[[package]] [[package]]
name = "lance-arrow-scalar" name = "lance-arrow-scalar"
version = "58.0.0" version = "58.0.0"
source = "git+https://github.com/lance-format/lance.git?tag=v10.0.0-beta.3#ed078e7c19c9560906e1eae54b0baf01dc509986" source = "git+https://github.com/lance-format/lance.git?tag=v10.0.0-beta.2#bbc04776fff39355a7287e6feacb0041395a45e1"
dependencies = [ dependencies = [
"arrow-array", "arrow-array",
"arrow-buffer", "arrow-buffer",
@@ -4889,7 +4889,7 @@ dependencies = [
[[package]] [[package]]
name = "lance-arrow-stats" name = "lance-arrow-stats"
version = "58.0.0" version = "58.0.0"
source = "git+https://github.com/lance-format/lance.git?tag=v10.0.0-beta.3#ed078e7c19c9560906e1eae54b0baf01dc509986" source = "git+https://github.com/lance-format/lance.git?tag=v10.0.0-beta.2#bbc04776fff39355a7287e6feacb0041395a45e1"
dependencies = [ dependencies = [
"arrow-array", "arrow-array",
"arrow-schema", "arrow-schema",
@@ -4898,8 +4898,8 @@ dependencies = [
[[package]] [[package]]
name = "lance-bitpacking" name = "lance-bitpacking"
version = "10.0.0-beta.3" version = "10.0.0-beta.2"
source = "git+https://github.com/lance-format/lance.git?tag=v10.0.0-beta.3#ed078e7c19c9560906e1eae54b0baf01dc509986" source = "git+https://github.com/lance-format/lance.git?tag=v10.0.0-beta.2#bbc04776fff39355a7287e6feacb0041395a45e1"
dependencies = [ dependencies = [
"arrayref", "arrayref",
"crunchy", "crunchy",
@@ -4909,8 +4909,8 @@ dependencies = [
[[package]] [[package]]
name = "lance-core" name = "lance-core"
version = "10.0.0-beta.3" version = "10.0.0-beta.2"
source = "git+https://github.com/lance-format/lance.git?tag=v10.0.0-beta.3#ed078e7c19c9560906e1eae54b0baf01dc509986" source = "git+https://github.com/lance-format/lance.git?tag=v10.0.0-beta.2#bbc04776fff39355a7287e6feacb0041395a45e1"
dependencies = [ dependencies = [
"arrow-array", "arrow-array",
"arrow-buffer", "arrow-buffer",
@@ -4948,8 +4948,8 @@ dependencies = [
[[package]] [[package]]
name = "lance-datafusion" name = "lance-datafusion"
version = "10.0.0-beta.3" version = "10.0.0-beta.2"
source = "git+https://github.com/lance-format/lance.git?tag=v10.0.0-beta.3#ed078e7c19c9560906e1eae54b0baf01dc509986" source = "git+https://github.com/lance-format/lance.git?tag=v10.0.0-beta.2#bbc04776fff39355a7287e6feacb0041395a45e1"
dependencies = [ dependencies = [
"arrow", "arrow",
"arrow-array", "arrow-array",
@@ -4979,8 +4979,8 @@ dependencies = [
[[package]] [[package]]
name = "lance-datagen" name = "lance-datagen"
version = "10.0.0-beta.3" version = "10.0.0-beta.2"
source = "git+https://github.com/lance-format/lance.git?tag=v10.0.0-beta.3#ed078e7c19c9560906e1eae54b0baf01dc509986" source = "git+https://github.com/lance-format/lance.git?tag=v10.0.0-beta.2#bbc04776fff39355a7287e6feacb0041395a45e1"
dependencies = [ dependencies = [
"arrow", "arrow",
"arrow-array", "arrow-array",
@@ -4997,8 +4997,8 @@ dependencies = [
[[package]] [[package]]
name = "lance-derive" name = "lance-derive"
version = "10.0.0-beta.3" version = "10.0.0-beta.2"
source = "git+https://github.com/lance-format/lance.git?tag=v10.0.0-beta.3#ed078e7c19c9560906e1eae54b0baf01dc509986" source = "git+https://github.com/lance-format/lance.git?tag=v10.0.0-beta.2#bbc04776fff39355a7287e6feacb0041395a45e1"
dependencies = [ dependencies = [
"proc-macro2", "proc-macro2",
"quote", "quote",
@@ -5007,8 +5007,8 @@ dependencies = [
[[package]] [[package]]
name = "lance-encoding" name = "lance-encoding"
version = "10.0.0-beta.3" version = "10.0.0-beta.2"
source = "git+https://github.com/lance-format/lance.git?tag=v10.0.0-beta.3#ed078e7c19c9560906e1eae54b0baf01dc509986" source = "git+https://github.com/lance-format/lance.git?tag=v10.0.0-beta.2#bbc04776fff39355a7287e6feacb0041395a45e1"
dependencies = [ dependencies = [
"arrow-arith", "arrow-arith",
"arrow-array", "arrow-array",
@@ -5043,8 +5043,8 @@ dependencies = [
[[package]] [[package]]
name = "lance-file" name = "lance-file"
version = "10.0.0-beta.3" version = "10.0.0-beta.2"
source = "git+https://github.com/lance-format/lance.git?tag=v10.0.0-beta.3#ed078e7c19c9560906e1eae54b0baf01dc509986" source = "git+https://github.com/lance-format/lance.git?tag=v10.0.0-beta.2#bbc04776fff39355a7287e6feacb0041395a45e1"
dependencies = [ dependencies = [
"arrow-arith", "arrow-arith",
"arrow-array", "arrow-array",
@@ -5074,8 +5074,8 @@ dependencies = [
[[package]] [[package]]
name = "lance-index" name = "lance-index"
version = "10.0.0-beta.3" version = "10.0.0-beta.2"
source = "git+https://github.com/lance-format/lance.git?tag=v10.0.0-beta.3#ed078e7c19c9560906e1eae54b0baf01dc509986" source = "git+https://github.com/lance-format/lance.git?tag=v10.0.0-beta.2#bbc04776fff39355a7287e6feacb0041395a45e1"
dependencies = [ dependencies = [
"arc-swap", "arc-swap",
"arrow", "arrow",
@@ -5142,8 +5142,8 @@ dependencies = [
[[package]] [[package]]
name = "lance-index-core" name = "lance-index-core"
version = "10.0.0-beta.3" version = "10.0.0-beta.2"
source = "git+https://github.com/lance-format/lance.git?tag=v10.0.0-beta.3#ed078e7c19c9560906e1eae54b0baf01dc509986" source = "git+https://github.com/lance-format/lance.git?tag=v10.0.0-beta.2#bbc04776fff39355a7287e6feacb0041395a45e1"
dependencies = [ dependencies = [
"arrow-array", "arrow-array",
"arrow-schema", "arrow-schema",
@@ -5165,8 +5165,8 @@ dependencies = [
[[package]] [[package]]
name = "lance-io" name = "lance-io"
version = "10.0.0-beta.3" version = "10.0.0-beta.2"
source = "git+https://github.com/lance-format/lance.git?tag=v10.0.0-beta.3#ed078e7c19c9560906e1eae54b0baf01dc509986" source = "git+https://github.com/lance-format/lance.git?tag=v10.0.0-beta.2#bbc04776fff39355a7287e6feacb0041395a45e1"
dependencies = [ dependencies = [
"arrow", "arrow",
"arrow-arith", "arrow-arith",
@@ -5209,8 +5209,8 @@ dependencies = [
[[package]] [[package]]
name = "lance-linalg" name = "lance-linalg"
version = "10.0.0-beta.3" version = "10.0.0-beta.2"
source = "git+https://github.com/lance-format/lance.git?tag=v10.0.0-beta.3#ed078e7c19c9560906e1eae54b0baf01dc509986" source = "git+https://github.com/lance-format/lance.git?tag=v10.0.0-beta.2#bbc04776fff39355a7287e6feacb0041395a45e1"
dependencies = [ dependencies = [
"arrow-array", "arrow-array",
"arrow-buffer", "arrow-buffer",
@@ -5226,8 +5226,8 @@ dependencies = [
[[package]] [[package]]
name = "lance-namespace" name = "lance-namespace"
version = "10.0.0-beta.3" version = "10.0.0-beta.2"
source = "git+https://github.com/lance-format/lance.git?tag=v10.0.0-beta.3#ed078e7c19c9560906e1eae54b0baf01dc509986" source = "git+https://github.com/lance-format/lance.git?tag=v10.0.0-beta.2#bbc04776fff39355a7287e6feacb0041395a45e1"
dependencies = [ dependencies = [
"arrow", "arrow",
"async-trait", "async-trait",
@@ -5239,8 +5239,8 @@ dependencies = [
[[package]] [[package]]
name = "lance-namespace-impls" name = "lance-namespace-impls"
version = "10.0.0-beta.3" version = "10.0.0-beta.2"
source = "git+https://github.com/lance-format/lance.git?tag=v10.0.0-beta.3#ed078e7c19c9560906e1eae54b0baf01dc509986" source = "git+https://github.com/lance-format/lance.git?tag=v10.0.0-beta.2#bbc04776fff39355a7287e6feacb0041395a45e1"
dependencies = [ dependencies = [
"arrow", "arrow",
"arrow-ipc", "arrow-ipc",
@@ -5294,8 +5294,8 @@ dependencies = [
[[package]] [[package]]
name = "lance-select" name = "lance-select"
version = "10.0.0-beta.3" version = "10.0.0-beta.2"
source = "git+https://github.com/lance-format/lance.git?tag=v10.0.0-beta.3#ed078e7c19c9560906e1eae54b0baf01dc509986" source = "git+https://github.com/lance-format/lance.git?tag=v10.0.0-beta.2#bbc04776fff39355a7287e6feacb0041395a45e1"
dependencies = [ dependencies = [
"arrow-array", "arrow-array",
"arrow-buffer", "arrow-buffer",
@@ -5310,8 +5310,8 @@ dependencies = [
[[package]] [[package]]
name = "lance-table" name = "lance-table"
version = "10.0.0-beta.3" version = "10.0.0-beta.2"
source = "git+https://github.com/lance-format/lance.git?tag=v10.0.0-beta.3#ed078e7c19c9560906e1eae54b0baf01dc509986" source = "git+https://github.com/lance-format/lance.git?tag=v10.0.0-beta.2#bbc04776fff39355a7287e6feacb0041395a45e1"
dependencies = [ dependencies = [
"arrow", "arrow",
"arrow-array", "arrow-array",
@@ -5350,8 +5350,8 @@ dependencies = [
[[package]] [[package]]
name = "lance-testing" name = "lance-testing"
version = "10.0.0-beta.3" version = "10.0.0-beta.2"
source = "git+https://github.com/lance-format/lance.git?tag=v10.0.0-beta.3#ed078e7c19c9560906e1eae54b0baf01dc509986" source = "git+https://github.com/lance-format/lance.git?tag=v10.0.0-beta.2#bbc04776fff39355a7287e6feacb0041395a45e1"
dependencies = [ dependencies = [
"arrow-array", "arrow-array",
"arrow-schema", "arrow-schema",
@@ -5364,8 +5364,8 @@ dependencies = [
[[package]] [[package]]
name = "lance-tokenizer" name = "lance-tokenizer"
version = "10.0.0-beta.3" version = "10.0.0-beta.2"
source = "git+https://github.com/lance-format/lance.git?tag=v10.0.0-beta.3#ed078e7c19c9560906e1eae54b0baf01dc509986" source = "git+https://github.com/lance-format/lance.git?tag=v10.0.0-beta.2#bbc04776fff39355a7287e6feacb0041395a45e1"
dependencies = [ dependencies = [
"icu_segmenter", "icu_segmenter",
"jieba-rs", "jieba-rs",
+14 -14
View File
@@ -13,20 +13,20 @@ categories = ["database-implementations"]
rust-version = "1.91.0" rust-version = "1.91.0"
[workspace.dependencies] [workspace.dependencies]
lance = { "version" = "=10.0.0-beta.3", default-features = false, "tag" = "v10.0.0-beta.3", "git" = "https://github.com/lance-format/lance.git" } lance = { path = "../lance/rust/lance", default-features = false }
lance-core = { "version" = "=10.0.0-beta.3", "tag" = "v10.0.0-beta.3", "git" = "https://github.com/lance-format/lance.git" } lance-core = { path = "../lance/rust/lance-core" }
lance-datagen = { "version" = "=10.0.0-beta.3", "tag" = "v10.0.0-beta.3", "git" = "https://github.com/lance-format/lance.git" } lance-datagen = { path = "../lance/rust/lance-datagen" }
lance-file = { "version" = "=10.0.0-beta.3", "tag" = "v10.0.0-beta.3", "git" = "https://github.com/lance-format/lance.git" } lance-file = { path = "../lance/rust/lance-file" }
lance-io = { "version" = "=10.0.0-beta.3", default-features = false, "tag" = "v10.0.0-beta.3", "git" = "https://github.com/lance-format/lance.git" } lance-io = { path = "../lance/rust/lance-io", default-features = false }
lance-index = { "version" = "=10.0.0-beta.3", "tag" = "v10.0.0-beta.3", "git" = "https://github.com/lance-format/lance.git" } lance-index = { path = "../lance/rust/lance-index" }
lance-linalg = { "version" = "=10.0.0-beta.3", "tag" = "v10.0.0-beta.3", "git" = "https://github.com/lance-format/lance.git" } lance-linalg = { path = "../lance/rust/lance-linalg" }
lance-namespace = { "version" = "=10.0.0-beta.3", "tag" = "v10.0.0-beta.3", "git" = "https://github.com/lance-format/lance.git" } lance-namespace = { path = "../lance/rust/lance-namespace" }
lance-namespace-impls = { "version" = "=10.0.0-beta.3", default-features = false, "tag" = "v10.0.0-beta.3", "git" = "https://github.com/lance-format/lance.git" } lance-namespace-impls = { path = "../lance/rust/lance-namespace-impls", default-features = false }
lance-table = { "version" = "=10.0.0-beta.3", "tag" = "v10.0.0-beta.3", "git" = "https://github.com/lance-format/lance.git" } lance-table = { path = "../lance/rust/lance-table" }
lance-testing = { "version" = "=10.0.0-beta.3", "tag" = "v10.0.0-beta.3", "git" = "https://github.com/lance-format/lance.git" } lance-testing = { path = "../lance/rust/lance-testing" }
lance-datafusion = { "version" = "=10.0.0-beta.3", "tag" = "v10.0.0-beta.3", "git" = "https://github.com/lance-format/lance.git" } lance-datafusion = { path = "../lance/rust/lance-datafusion" }
lance-encoding = { "version" = "=10.0.0-beta.3", "tag" = "v10.0.0-beta.3", "git" = "https://github.com/lance-format/lance.git" } lance-encoding = { path = "../lance/rust/lance-encoding" }
lance-arrow = { "version" = "=10.0.0-beta.3", "tag" = "v10.0.0-beta.3", "git" = "https://github.com/lance-format/lance.git" } lance-arrow = { path = "../lance/rust/lance-arrow" }
ahash = "0.8" ahash = "0.8"
# Note that this one does not include pyarrow # Note that this one does not include pyarrow
arrow = { version = "58.0.0", optional = false } arrow = { version = "58.0.0", optional = false }
-13
View File
@@ -43,19 +43,6 @@ The following tokenizers are available:
*** ***
### blockSize?
```ts
optional blockSize: 128 | 256;
```
Number of documents per compressed posting block.
The default is 128. Supported values are 128 and 256. A value of 256 uses
the experimental FTS V3 format and may introduce breaking changes.
***
### language? ### language?
```ts ```ts
+1 -1
View File
@@ -28,7 +28,7 @@
<properties> <properties>
<project.build.sourceEncoding>UTF-8</project.build.sourceEncoding> <project.build.sourceEncoding>UTF-8</project.build.sourceEncoding>
<arrow.version>15.0.0</arrow.version> <arrow.version>15.0.0</arrow.version>
<lance-core.version>10.0.0-beta.3</lance-core.version> <lance-core.version>10.0.0-beta.2</lance-core.version>
<spotless.skip>false</spotless.skip> <spotless.skip>false</spotless.skip>
<spotless.version>2.30.0</spotless.version> <spotless.version>2.30.0</spotless.version>
<spotless.java.googlejavaformat.version>1.7</spotless.java.googlejavaformat.version> <spotless.java.googlejavaformat.version>1.7</spotless.java.googlejavaformat.version>
-49
View File
@@ -15,7 +15,6 @@ import {
OAuthHeaderProvider, OAuthHeaderProvider,
StaticHeaderProvider, StaticHeaderProvider,
} from "../lancedb/header"; } from "../lancedb/header";
import { Index } from "../lancedb/indices";
// Test-only header providers // Test-only header providers
class CustomProvider extends HeaderProvider { class CustomProvider extends HeaderProvider {
@@ -226,54 +225,6 @@ describe("remote connection", () => {
); );
}); });
it("sends the FTS posting block size to remote tables", async () => {
let createIndexBody: Record<string, unknown> | undefined;
await withMockDatabase(
(req, res) => {
const path = req.url ?? "";
if (path.endsWith("/describe/")) {
res.writeHead(200, { "Content-Type": "application/json" }).end(
JSON.stringify({
name: "t",
version: 1,
schema: {
fields: [
{ name: "text", type: { type: "string" }, nullable: false },
],
},
}),
);
return;
}
if (path.endsWith("/create_index/")) {
let raw = "";
req.on("data", (chunk) => {
raw += chunk;
});
req.on("end", () => {
createIndexBody = JSON.parse(raw);
res.writeHead(200).end();
});
return;
}
res.writeHead(404).end();
},
async (db) => {
const table = await db.openTable("t");
await table.createIndex("text", {
config: Index.fts({ blockSize: 256 }),
});
},
);
expect(createIndexBody?.["column"]).toBe("text");
expect(createIndexBody?.["index_type"]).toBe("FTS");
expect(createIndexBody?.["block_size"]).toBe(256);
});
it("diffs and merges remote branches", async () => { it("diffs and merges remote branches", async () => {
const sampleDiff = { const sampleDiff = {
fromBranch: "exp", fromBranch: "exp",
-29
View File
@@ -2527,35 +2527,6 @@ describe.each([arrow15, arrow16, arrow17, arrow18])(
expect(results3.length).toBe(1); expect(results3.length).toBe(1);
}); });
test("full text search with custom posting block size", async () => {
const db = await connect(tmpDir.name);
const data = [
{ text: "hello world", vector: [0.1, 0.2, 0.3] },
{ text: "goodbye world", vector: [0.4, 0.5, 0.6] },
];
const table = await db.createTable("test", data);
await table.createIndex("text", {
config: Index.fts({ blockSize: 256 }),
});
const index = (await table.listIndices()).find(
(index) => index.indexType === "FTS",
);
expect(index?.indexVersion).toBe(3);
expect(
(index?.indexDetails as Record<string, unknown>)["block_size"],
).toBe(256);
const results = await table.search("hello").toArray();
expect(results[0].text).toBe(data[0].text);
});
test("rejects invalid full text posting block size", () => {
expect(() => Index.fts({ blockSize: 129 as 128 | 256 })).toThrow(
"128 or 256",
);
});
test("full text search without lowercase", async () => { test("full text search without lowercase", async () => {
const db = await connect(tmpDir.name); const db = await connect(tmpDir.name);
const data = [ const data = [
-9
View File
@@ -572,14 +572,6 @@ export interface FtsOptions {
* whether to only index the prefix of the token for ngram tokenizer * whether to only index the prefix of the token for ngram tokenizer
*/ */
prefixOnly?: boolean; prefixOnly?: boolean;
/**
* Number of documents per compressed posting block.
*
* The default is 128. Supported values are 128 and 256. A value of 256 uses
* the experimental FTS V3 format and may introduce breaking changes.
*/
blockSize?: 128 | 256;
} }
export class Index { export class Index {
@@ -759,7 +751,6 @@ export class Index {
options?.ngramMinLength, options?.ngramMinLength,
options?.ngramMaxLength, options?.ngramMaxLength,
options?.prefixOnly, options?.prefixOnly,
options?.blockSize,
), ),
); );
} }
+3 -9
View File
@@ -226,8 +226,7 @@ impl Index {
ngram_min_length: Option<u32>, ngram_min_length: Option<u32>,
ngram_max_length: Option<u32>, ngram_max_length: Option<u32>,
prefix_only: Option<bool>, prefix_only: Option<bool>,
block_size: Option<u32>, ) -> Self {
) -> napi::Result<Self> {
let mut opts = FtsIndexBuilder::default(); let mut opts = FtsIndexBuilder::default();
if let Some(with_position) = with_position { if let Some(with_position) = with_position {
opts = opts.with_position(with_position); opts = opts.with_position(with_position);
@@ -262,15 +261,10 @@ impl Index {
if let Some(prefix_only) = prefix_only { if let Some(prefix_only) = prefix_only {
opts = opts.ngram_prefix_only(prefix_only); opts = opts.ngram_prefix_only(prefix_only);
} }
if let Some(block_size) = block_size {
opts = opts
.block_size(block_size as usize)
.map_err(|err| napi::Error::from_reason(err.to_string()))?;
}
Ok(Self { Self {
inner: Mutex::new(Some(LanceDbIndex::FTS(opts))), inner: Mutex::new(Some(LanceDbIndex::FTS(opts))),
}) }
} }
#[napi(factory)] #[napi(factory)]
+1 -1
View File
@@ -1,5 +1,5 @@
[tool.bumpversion] [tool.bumpversion]
current_version = "0.35.0-beta.3" current_version = "0.35.0-beta.2"
parse = """(?x) parse = """(?x)
(?P<major>0|[1-9]\\d*)\\. (?P<major>0|[1-9]\\d*)\\.
(?P<minor>0|[1-9]\\d*)\\. (?P<minor>0|[1-9]\\d*)\\.
+1 -1
View File
@@ -1,6 +1,6 @@
[package] [package]
name = "lancedb-python" name = "lancedb-python"
version = "0.35.0-beta.3" version = "0.35.0-beta.2"
publish = false publish = false
edition.workspace = true edition.workspace = true
description = "Python bindings for LanceDB" description = "Python bindings for LanceDB"
-11
View File
@@ -115,12 +115,6 @@ class FTS:
For example, it works with `title`, `description`, `content`, etc. For example, it works with `title`, `description`, `content`, etc.
Examples
--------
Create an index configuration that uses 256-document posting blocks:
>>> config = FTS(block_size=256)
Attributes Attributes
---------- ----------
with_position : bool, default False with_position : bool, default False
@@ -154,10 +148,6 @@ class FTS:
ascii_folding : bool, default True ascii_folding : bool, default True
Whether to fold ASCII characters. This converts accented characters to Whether to fold ASCII characters. This converts accented characters to
their ASCII equivalent. For example, "café" would be converted to "cafe". their ASCII equivalent. For example, "café" would be converted to "cafe".
block_size : int, default 128
The number of documents per compressed posting block. Supported values
are 128 and 256. A value of 256 uses the experimental FTS V3 format
and may introduce breaking changes.
Notes Notes
----- -----
@@ -178,7 +168,6 @@ class FTS:
ngram_min_length: int = 3 ngram_min_length: int = 3
ngram_max_length: int = 3 ngram_max_length: int = 3
prefix_only: bool = False prefix_only: bool = False
block_size: int = 128
@dataclass @dataclass
-2
View File
@@ -344,7 +344,6 @@ class RemoteTable(Table):
ngram_min_length: int = 3, ngram_min_length: int = 3,
ngram_max_length: int = 3, ngram_max_length: int = 3,
prefix_only: bool = False, prefix_only: bool = False,
block_size: int = 128,
name: Optional[str] = None, name: Optional[str] = None,
): ):
"""Create a full-text search index on a column. """Create a full-text search index on a column.
@@ -365,7 +364,6 @@ class RemoteTable(Table):
ngram_min_length=ngram_min_length, ngram_min_length=ngram_min_length,
ngram_max_length=ngram_max_length, ngram_max_length=ngram_max_length,
prefix_only=prefix_only, prefix_only=prefix_only,
block_size=block_size,
) )
LOOP.run( LOOP.run(
self._table.create_index( self._table.create_index(
@@ -23,7 +23,7 @@ class AnswerdotaiRerankers(Reranker):
column : str, default "text" column : str, default "text"
The name of the column to use as input to the cross encoder model. The name of the column to use as input to the cross encoder model.
return_score : str, default "relevance" return_score : str, default "relevance"
options are "relevance" or "all". options are "relevance" or "all". Only "relevance" is supported for now.
**kwargs **kwargs
Additional keyword arguments to pass to the model. For example, 'device'. Additional keyword arguments to pass to the model. For example, 'device'.
See AnswerDotAI/rerankers for more information. See AnswerDotAI/rerankers for more information.
@@ -77,13 +77,12 @@ class AnswerdotaiRerankers(Reranker):
vector_results: pa.Table, vector_results: pa.Table,
fts_results: pa.Table, fts_results: pa.Table,
): ):
if self.score == "all": combined_results = self.merge_results(vector_results, fts_results)
combined_results = self._merge_and_keep_scores(vector_results, fts_results)
else:
combined_results = self.merge_results(vector_results, fts_results)
combined_results = self._rerank(combined_results, query) combined_results = self._rerank(combined_results, query)
if self.score == "relevance": if self.score == "relevance":
combined_results = self._keep_relevance_score(combined_results) combined_results = self._keep_relevance_score(combined_results)
elif self.score == "all":
combined_results = self._merge_and_keep_scores(vector_results, fts_results)
combined_results = combined_results.sort_by( combined_results = combined_results.sort_by(
[("_relevance_score", "descending")] [("_relevance_score", "descending")]
) )
+1 -1
View File
@@ -16,7 +16,7 @@ class ColbertReranker(AnswerdotaiRerankers):
column : str, default "text" column : str, default "text"
The name of the column to use as input to the cross encoder model. The name of the column to use as input to the cross encoder model.
return_score : str, default "relevance" return_score : str, default "relevance"
options are "relevance" or "all". options are "relevance" or "all". Only "relevance" is supported for now.
**kwargs **kwargs
Additional keyword arguments to pass to the model, for example, 'device'. Additional keyword arguments to pass to the model, for example, 'device'.
See AnswerDotAI/rerankers for more information. See AnswerDotAI/rerankers for more information.
+3 -7
View File
@@ -1106,7 +1106,6 @@ class Table(ABC):
ngram_min_length: int = 3, ngram_min_length: int = 3,
ngram_max_length: int = 3, ngram_max_length: int = 3,
prefix_only: bool = False, prefix_only: bool = False,
block_size: int = 128,
wait_timeout: Optional[timedelta] = None, wait_timeout: Optional[timedelta] = None,
name: Optional[str] = None, name: Optional[str] = None,
): ):
@@ -1178,10 +1177,6 @@ class Table(ABC):
The maximum length of an n-gram. The maximum length of an n-gram.
prefix_only: bool, default False prefix_only: bool, default False
Whether to only index the prefix of the token for ngram tokenizer. Whether to only index the prefix of the token for ngram tokenizer.
block_size: int, default 128
The number of documents per compressed posting block. Must be 128
or 256. A value of 256 uses the experimental FTS V3 format and
may introduce breaking changes.
wait_timeout: timedelta, optional wait_timeout: timedelta, optional
The timeout to wait if indexing is asynchronous. The timeout to wait if indexing is asynchronous.
name: str, optional name: str, optional
@@ -3031,7 +3026,6 @@ class LanceTable(Table):
ngram_min_length: int = 3, ngram_min_length: int = 3,
ngram_max_length: int = 3, ngram_max_length: int = 3,
prefix_only: bool = False, prefix_only: bool = False,
block_size: int = 128,
name: Optional[str] = None, name: Optional[str] = None,
): ):
"""Create a full-text search index on a column. """Create a full-text search index on a column.
@@ -3081,7 +3075,9 @@ class LanceTable(Table):
else: else:
tokenizer_configs = self.infer_tokenizer_configs(tokenizer_name) tokenizer_configs = self.infer_tokenizer_configs(tokenizer_name)
config = FTS(block_size=block_size, **tokenizer_configs) config = FTS(
**tokenizer_configs,
)
try: try:
LOOP.run( LOOP.run(
-17
View File
@@ -226,23 +226,6 @@ def test_create_inverted_index(table, with_position):
assert any(i.name == "custom_fts_index" for i in fts_indices) assert any(i.name == "custom_fts_index" for i in fts_indices)
@pytest.mark.parametrize("block_size", [128, 256])
def test_create_inverted_index_block_size(table, block_size):
table.create_index("text", config=FTS(block_size=block_size))
index = next(index for index in table.list_indices() if index.index_type == "FTS")
assert index.index_details["block_size"] == block_size
assert index.index_version == (2 if block_size == 128 else 3)
results = table.search("puppy").limit(5).to_list()
assert len(results) == 5
def test_create_inverted_index_rejects_invalid_block_size(table):
with pytest.raises(ValueError, match="128 or 256"):
table.create_index("text", config=FTS(block_size=129))
def test_search_fts(table): def test_search_fts(table):
table.create_fts_index("text") table.create_fts_index("text")
results = table.search("puppy").select(["id", "text"]).limit(5).to_list() results = table.search("puppy").select(["id", "text"]).limit(5).to_list()
+2 -7
View File
@@ -768,10 +768,7 @@ def test_table_create_indices():
# Test create_fts_index with custom name (legacy method) # Test create_fts_index with custom name (legacy method)
with pytest.warns(DeprecationWarning, match="create_fts_index"): with pytest.warns(DeprecationWarning, match="create_fts_index"):
table.create_fts_index( table.create_fts_index(
"text", "text", wait_timeout=timedelta(seconds=2), name="custom_fts_idx"
wait_timeout=timedelta(seconds=2),
block_size=256,
name="custom_fts_idx",
) )
# Test create_index with custom name (legacy form: vector_column_name kwarg) # Test create_index with custom name (legacy form: vector_column_name kwarg)
@@ -794,7 +791,6 @@ def test_table_create_indices():
fts_req = received_requests[1] fts_req = received_requests[1]
assert "name" in fts_req assert "name" in fts_req
assert fts_req["name"] == "custom_fts_idx" assert fts_req["name"] == "custom_fts_idx"
assert fts_req["block_size"] == 256
# Check vector index request has custom name # Check vector index request has custom name
vector_req = received_requests[2] vector_req = received_requests[2]
@@ -880,7 +876,7 @@ def test_remote_create_index_new_api():
_warnings.simplefilter("error", DeprecationWarning) _warnings.simplefilter("error", DeprecationWarning)
table.create_index("vector", config=IvfPq(distance_type="l2")) table.create_index("vector", config=IvfPq(distance_type="l2"))
table.create_index("category", config=BTree()) table.create_index("category", config=BTree())
table.create_index("text", config=FTS(block_size=256)) table.create_index("text", config=FTS())
# IvfRq via new API # IvfRq via new API
table.create_index("vector", config=IvfRq(distance_type="l2")) table.create_index("vector", config=IvfRq(distance_type="l2"))
@@ -900,7 +896,6 @@ def test_remote_create_index_new_api():
"vector", "vector",
"vector", "vector",
] ]
assert received_requests[2]["block_size"] == 256
def test_table_wait_for_index_timeout(): def test_table_wait_for_index_timeout():
-15
View File
@@ -644,21 +644,6 @@ def test_cross_encoder_reranker_return_all(tmp_path):
assert "_distance" in result.column_names assert "_distance" in result.column_names
def test_answerdotai_reranker_return_all(tmp_path):
pytest.importorskip("rerankers")
reranker = AnswerdotaiRerankers(return_score="all")
table, schema = get_test_table(tmp_path)
query = "single player experience"
result = (
table.search(query, query_type="hybrid", vector_column_name="vector")
.rerank(reranker=reranker)
.to_arrow()
)
assert "_relevance_score" in result.column_names
assert "_score" in result.column_names
assert "_distance" in result.column_names
# --------------------------------------------------------------------------- # ---------------------------------------------------------------------------
# Regression tests for LinearCombinationReranker scoring bugs (issue #3154) # Regression tests for LinearCombinationReranker scoring bugs (issue #3154)
# --------------------------------------------------------------------------- # ---------------------------------------------------------------------------
-4
View File
@@ -60,9 +60,6 @@ pub fn extract_index_params(source: &Option<Bound<'_, PyAny>>) -> PyResult<Lance
.ngram_min_length(params.ngram_min_length) .ngram_min_length(params.ngram_min_length)
.ngram_max_length(params.ngram_max_length) .ngram_max_length(params.ngram_max_length)
.ngram_prefix_only(params.prefix_only); .ngram_prefix_only(params.prefix_only);
let inner_opts = inner_opts
.block_size(params.block_size)
.map_err(|err| PyValueError::new_err(err.to_string()))?;
Ok(LanceDbIndex::FTS(inner_opts)) Ok(LanceDbIndex::FTS(inner_opts))
} }
"IvfFlat" => { "IvfFlat" => {
@@ -210,7 +207,6 @@ struct FtsParams {
ngram_min_length: u32, ngram_min_length: u32,
ngram_max_length: u32, ngram_max_length: u32,
prefix_only: bool, prefix_only: bool,
block_size: usize,
} }
#[derive(FromPyObject)] #[derive(FromPyObject)]
+23 -15
View File
@@ -273,11 +273,15 @@ pub(crate) async fn take_blobs_aligned(
if *is_null { if *is_null {
builder.append_null(); builder.append_null();
} else { } else {
if let Some(data) = &payloads[payload_idx].data { let data = payloads[payload_idx]
builder.append_value(data); .data
} else { .as_ref()
builder.append_null(); .ok_or_else(|| Error::Runtime {
} message: format!(
"blob read for column '{column}' returned null payload for a non-null row"
),
})?;
builder.append_value(data);
payload_idx += 1; payload_idx += 1;
} }
} }
@@ -313,16 +317,20 @@ pub(crate) async fn take_blob_files_aligned(
} }
let mut handles = handles.into_iter(); let mut handles = handles.into_iter();
Ok(null_mask let mut aligned_handles = Vec::with_capacity(row_ids.len());
.iter() for is_null in null_mask {
.map(|is_null| { if is_null {
if *is_null { aligned_handles.push(None);
None } else {
} else { let handle = handles.next().unwrap().ok_or_else(|| Error::Runtime {
handles.next().flatten() message: format!(
} "blob take for column '{column}' returned a null handle for a non-null row"
}) ),
.collect()) })?;
aligned_handles.push(Some(handle));
}
}
Ok(aligned_handles)
} }
#[cfg(test)] #[cfg(test)]
+1 -20
View File
@@ -54,26 +54,7 @@ pub enum Index {
/// substrings of the raw bytes, unlike the tokenized [`Index::FTS`] index. /// substrings of the raw bytes, unlike the tokenized [`Index::FTS`] index.
Fm(FmIndexBuilder), Fm(FmIndexBuilder),
/// Full text search index using BM25. /// Full text search index using bm25.
///
/// The posting block size defaults to 128. Supported values are 128 and 256;
/// a value of 256 uses the experimental FTS V3 format and may introduce
/// breaking changes.
///
/// ```
/// use lancedb::index::{Index, scalar::FtsIndexBuilder};
///
/// # async fn create_fts_index(
/// # table: &lancedb::Table,
/// # ) -> Result<(), Box<dyn std::error::Error>> {
/// let params = FtsIndexBuilder::default().block_size(256)?;
/// table
/// .create_index(&["text"], Index::FTS(params))
/// .execute()
/// .await?;
/// # Ok(())
/// # }
/// ```
FTS(FtsIndexBuilder), FTS(FtsIndexBuilder),
/// IVF index /// IVF index
-9
View File
@@ -4496,15 +4496,6 @@ mod tests {
serde_json::to_value(InvertedIndexParams::default()).unwrap(), serde_json::to_value(InvertedIndexParams::default()).unwrap(),
Index::FTS(Default::default()), Index::FTS(Default::default()),
), ),
(
"FTS",
{
let mut body = serde_json::to_value(InvertedIndexParams::default()).unwrap();
body["block_size"] = 256.into();
body
},
Index::FTS(InvertedIndexParams::default().block_size(256).unwrap()),
),
]; ];
for (index_type, expected_body, index) in cases { for (index_type, expected_body, index) in cases {
+2 -11
View File
@@ -382,9 +382,7 @@ mod tests {
use crate::connect; use crate::connect;
use crate::connection::ConnectBuilder; use crate::connection::ConnectBuilder;
use crate::index::Index; use crate::index::Index;
use crate::index::scalar::{ use crate::index::scalar::{BTreeIndexBuilder, BitmapIndexBuilder, FmIndexBuilder};
BTreeIndexBuilder, BitmapIndexBuilder, FmIndexBuilder, FtsIndexBuilder,
};
use crate::index::vector::{ use crate::index::vector::{
IvfHnswFlatIndexBuilder, IvfHnswPqIndexBuilder, IvfHnswSqIndexBuilder, IvfHnswFlatIndexBuilder, IvfHnswPqIndexBuilder, IvfHnswSqIndexBuilder,
}; };
@@ -1364,10 +1362,7 @@ mod tests {
.unwrap(); .unwrap();
table table
.create_index( .create_index(&["text"], Index::FTS(Default::default()))
&["text"],
Index::FTS(FtsIndexBuilder::default().block_size(256).unwrap()),
)
.execute() .execute()
.await .await
.unwrap(); .unwrap();
@@ -1377,10 +1372,6 @@ mod tests {
assert_eq!(index.index_type, crate::index::IndexType::FTS); assert_eq!(index.index_type, crate::index::IndexType::FTS);
assert_eq!(index.columns, vec!["text".to_string()]); assert_eq!(index.columns, vec!["text".to_string()]);
assert_eq!(index.name, "text_idx"); assert_eq!(index.name, "text_idx");
assert_eq!(index.index_version, Some(3));
let index_params: FtsIndexBuilder =
serde_json::from_str(index.index_details.as_deref().unwrap()).unwrap();
assert_eq!(index_params.posting_block_size(), 256);
let num_rows = 120; let num_rows = 120;
let stats = table.index_stats("text_idx").await.unwrap().unwrap(); let stats = table.index_stats("text_idx").await.unwrap().unwrap();