`lancedb.databases` maps a name to a location, mutually exclusive with `uri`. `search(sources=[…])` selects which to search, `sources=None` searches all of them and `sources=[]` searches none; `SearchResult.source` carries the configured name, so a path or URI never leaves the configuration. A database named in config keeps its name even when it is the only one configured; only a legacy single `uri` leaves `source` unset. Databases open on first use, not at entry. Which are searched is a per-query choice, so a set of 25 queried a few at a time opens a few, and a database nobody asked for can neither fail a query nor be opened for nothing. A named database that fails to open raises `SourceUnavailableError` naming it, raised outside the handler so the original is not attached at all. A local failure spells out the absolute path and an object-store failure can carry the bucket; `from None` would only stop that being printed, leaving it on `__context__` for anything that walks the chain. A legacy `uri` client has no name to report instead, so its error passes through unchanged. Candidates are fetched concurrently, then fused before anything is ranked. A configured reranker scores the union, which is what makes ranking across databases tractable: it compares query against document and does not care where a candidate came from. Without one, reciprocal rank fusion over the per-database rankings, since scores from separate indexes are not comparable. Enrichment then runs on the survivors through the database each came from, concurrently, so it costs what a single-database search costs. The over-fetch decision and the reranker belong to the federating client alone. Deciding per database would have each consult its own, and a local reranker loads model weights per instance. It is built only for a text query, and closed once by the client that owns it. A location without a scheme is opened as a local path rather than through `lancedb.uri`. Routing it through `uri` had `ConnectionMode` classify it as object storage, which opens a missing database instead of reporting it. With several databases configured, `store` and the repositories are left unset: they have no unambiguous meaning across a set, and picking one silently would be worse than the error.
19 lines
580 B
Python
19 lines
580 B
Python
class ReadOnlyError(Exception):
|
|
"""Raised when a write operation is attempted on a read-only store."""
|
|
|
|
pass
|
|
|
|
|
|
class MigrationRequiredError(Exception):
|
|
"""Database requires migration. Run 'haiku-rag migrate' to upgrade."""
|
|
|
|
pass
|
|
|
|
|
|
class SourceUnavailableError(Exception):
|
|
"""A configured database could not be opened.
|
|
|
|
Carries the configured name and never the location: a path or URI in an
|
|
error message travels into logs and into whatever a consumer renders, and
|
|
the point of naming databases is that locations stay in the configuration.
|
|
"""
|