fix(search): validate effort examples and hybrid queries

This commit is contained in:
Yang Cen
2026-10-11 17:38:14 +08:00
parent 13853cb169
commit 1e545e9835
3 changed files with 69 additions and 5 deletions
+21 -4
View File
@@ -1734,6 +1734,9 @@ class LanceVectorQueryBuilder(LanceQueryBuilder):
Examples
--------
>>> import lancedb
>>> db = lancedb.connect("memory://")
>>> table = db.create_table("effort_vectors", [{"vector": [0.1, 0.2]}])
>>> query = table.search([0.1, 0.2]).search_effort(0.75)
"""
self._search_effort = search_effort
@@ -2562,11 +2565,17 @@ class LanceHybridQueryBuilder(LanceQueryBuilder):
Examples
--------
>>> query = table.search([0.1, 0.2]).search_effort(0.75)
>>> import lancedb
>>> db = lancedb.connect("memory://")
>>> table = db.create_table(
... "effort_hybrid", [{"vector": [0.1, 0.2], "text": "dog"}]
... )
>>> query = (
... table.search(query_type="hybrid").vector([0.1, 0.2])
... .text("dog").search_effort(0.75)
... )
"""
self._search_effort = search_effort
if self._vector_query is not None:
self._vector_query.search_effort(search_effort)
return self
def minimum_nprobes(self, minimum_nprobes: int) -> LanceHybridQueryBuilder:
@@ -3790,7 +3799,15 @@ class AsyncVectorQueryBase:
Examples
--------
>>> query = table.vector_search([0.1, 0.2]).search_effort(0.75)
>>> import asyncio
>>> import lancedb
>>> async def build_query():
... db = await lancedb.connect_async("memory://")
... table = await db.create_table(
... "effort_async", [{"vector": [0.1, 0.2]}]
... )
... return table.vector_search([0.1, 0.2]).search_effort(0.75)
>>> query = asyncio.run(build_query())
"""
self._inner.search_effort(search_effort)
return self
+16 -1
View File
@@ -2284,6 +2284,7 @@ def test_search_effort_probe_budget(tmp_path, monkeypatch, metric, effort, probe
data = pa.table(
{
"id": np.arange(512),
"text": ["dog"] * 512,
"vector": pa.FixedSizeListArray.from_arrays(pa.array(vectors.ravel()), 16),
}
)
@@ -2298,7 +2299,8 @@ def test_search_effort_probe_budget(tmp_path, monkeypatch, metric, effort, probe
return table.search(vector).distance_type(metric).search_effort(value).limit(8)
def partitions(query):
values = re.findall(r"partitions_searched=(\d+)", query.analyze_plan())
vector_plan = query.analyze_plan().split("FTS Search Plan:", 1)[0]
values = re.findall(r"partitions_searched=(\d+)", vector_plan)
assert values
return sum(map(int, values))
@@ -2335,6 +2337,19 @@ def test_search_effort_probe_budget(tmp_path, monkeypatch, metric, effort, probe
assert partitions(filtered) <= 2
assert all(row["id"] % 8 == 0 for row in filtered.to_list())
if metric == "l2" and effort == 0.5:
table.create_index("text", config=FTS())
hybrid = (
table.search(query_type="hybrid")
.vector(vector)
.text("dog")
.nprobes(1)
.search_effort(0.5)
.limit(8)
)
assert partitions(hybrid) == 4
assert partitions(hybrid.search_effort(None)) == 1
@pytest.mark.parametrize(
"effort", [-0.1, 1.1, float("nan"), float("inf"), -float("inf")]