Skip to content

feat: add vector-search helpers (cosine/l2/dot distance UDFs, semantic_search) - #40

Merged
rohan-hotdata merged 2 commits into
mainfrom
feat/vector-search-helpers
Jul 22, 2026
Merged

feat: add vector-search helpers (cosine/l2/dot distance UDFs, semantic_search)#40
rohan-hotdata merged 2 commits into
mainfrom
feat/vector-search-helpers

Conversation

@rohan-hotdata

@rohan-hotdata rohan-hotdata commented Jul 22, 2026

Copy link
Copy Markdown
Contributor

Summary

  • Adds ibis_hotdata.vector: cosine_distance, l2_distance, negative_dot_product (@ibis.udf.scalar.builtin stubs) plus semantic_search(table, column, query_vector, k, ...), a query builder for HNSW-indexed vector columns.
  • Compiles to ORDER BY <distance>(col, ARRAY[...]) ASC LIMIT k with the vector column excluded from the output — the SQL shape the engine's USearchRule index-selection requires (query vector as a literal ARRAY[...], distance aliased, embedding column never in the output — see engine issue #508).
  • No backend changes — this is a pure helper layer on top of the existing Postgres-dialect compiler.

Verification

  • Compile-only unit tests (tests/test_vector.py) assert the exact SQL shape: literal array, aliased distance, source column excluded from output, ORDER BY ... ASC LIMIT k, custom distance_fn/distance_name honored.
  • Full offline suite passes (109 tests), ruff clean.
  • Live-verified end to end against a real workspace (examples/06_semantic_search.py): correct nearest-neighbor ordering for both cosine_distance and l2_distance against a toy embedding table, through the full create → load → query → drop lifecycle.

Note

This branch and #41 (presigned-upload-flow fix) both touch CHANGELOG.md's [Unreleased] section at the same anchor point — expect a small, easy textual conflict when the second one merges; no code overlap.

Test plan

  • uv run pytest
  • uv run ruff check src tests examples
  • Live run against a real workspace

🤖 Generated with Claude Code

…c_search)

Adds ibis_hotdata.vector: three @ibis.udf.scalar.builtin distance-function
stubs plus a semantic_search(table, column, query_vector, k) query builder,
compiling to ORDER BY <distance>(...) ASC LIMIT k with the vector column
excluded from output -- the SQL shape the engine's HNSW index-selection rule
requires. Verified via ibis.to_sql compile-only tests, and live against a
local-cluster workspace (examples/06_semantic_search.py).
@rohan-hotdata
rohan-hotdata requested a review from a team as a code owner July 22, 2026 04:33
@rohan-hotdata
rohan-hotdata requested review from zfarrell and removed request for a team July 22, 2026 04:33
qvec = ibis.literal(list(query_vector))
return (
table.select(*other_cols, **{distance_name: distance_fn(col, qvec)})
.order_by(ibis.asc(distance_name))

Copy link
Copy Markdown

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

super nit: (not blocking) if table already has a column named distance_name (default "distance"), it ends up in both other_cols and the **{distance_name: ...} kwarg, and select raises a duplicate-column error. Not worth guarding against for the common case, but a one-line note in the docstring that distance_name must not collide with an existing column would save a confusing traceback.

claude[bot]
claude Bot previously approved these changes Jul 22, 2026
Review nit on #40: if table already has a column named distance_name
(default "distance"), select raises a duplicate-column error since it
ends up in both other_cols and the aliased distance kwarg.

@claude claude Bot left a comment

Copy link
Copy Markdown

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Clean, well-tested vector-search helper layer. The prior super nit about distance_name collisions is now documented in the docstring. No blocking issues.

@rohan-hotdata
rohan-hotdata merged commit eebe298 into main Jul 22, 2026
8 checks passed
rohan-hotdata added a commit that referenced this pull request Jul 22, 2026
The conflict resolution merging #40 dropped the blank line between the
Fixed and Added sections under Unreleased.
rohan-hotdata added a commit that referenced this pull request Jul 22, 2026
…41)

* fix: migrate create_table's upload path to the presigned upload flow

runtimedb PR #952 removed the legacy POST /v1/files endpoint in favor of
the presigned direct-to-storage flow (POST /v1/uploads -> PUT -> finalize).
hotdata-ibis's create_table/upload_file called the now-dead endpoint via
the SDK's generated UploadsApi.upload_file, breaking every write against
any runtimedb deployment past that commit (confirmed on production).

Switches to hotdata.uploads.UploadsApi (the SDK's own hand-written
orchestration of the presigned flow: session create, storage PUT,
finalize, with retries/multipart handling) instead of hand-rolling the
flow here. No SDK version bump needed -- hotdata.uploads is already
present across the whole >=0.7,<0.9 pin range.

upload_file's return value now carries upload_id (FinalizeUploadResponse)
instead of id (the old UploadResponse). Test fixtures updated to mock the
three-stage presigned flow instead of the single POST /v1/files call.

Verified: full offline suite (101 tests) against the updated flow, and
live against production (api.hotdata.dev, where /v1/files is confirmed
404) -- examples 01, 03, 04, 05, and the vector-search example all pass
end to end, including the create_database -> create_table -> query ->
drop_database write/read cycle.

* docs: restore blank line between CHANGELOG sections

The conflict resolution merging #40 dropped the blank line between the
Fixed and Added sections under Unreleased.
@rohan-hotdata
rohan-hotdata deleted the feat/vector-search-helpers branch July 22, 2026 05:33
@zfarrell

Copy link
Copy Markdown
Contributor

approved

Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment

Labels

None yet

Projects

None yet

Development

Successfully merging this pull request may close these issues.

2 participants