Correct what the client and the docs claim
`HaikuRAG.__init__` said an omitted `db_path` uses `storage.data_dir`, which is the last of three; and that `sources` is ignored for a single `uri`, where it raises, since only `lancedb.databases` names databases. The name is not the only identity leaving the configuration: results, citations, model input and errors opening a named database carry it, while `info`, `init` and `tag` print the location. `sources=[]` returns no search results, but `ask` and `analyze` still answer, without evidence. Trim the comments that still narrated a failure or an alternative to the invariant they were there for.
This commit is contained in:
parent
ca2e28559e
commit
8f41d42ab2
7 changed files with 31 additions and 40 deletions
|
|
@ -214,9 +214,10 @@ lancedb:
|
||||||
A location is a URI or a local path. `databases` and `uri` are mutually
|
A location is a URI or a local path. `databases` and `uri` are mutually
|
||||||
exclusive, and setting both fails validation.
|
exclusive, and setting both fails validation.
|
||||||
|
|
||||||
The name is the only identity that leaves the configuration. Results, citations
|
Results, citations, model input and errors opening a named database carry the
|
||||||
and error messages carry it, so a path or a bucket never reaches a log, a trace
|
configured name rather than the location, so a path or a bucket does not reach a
|
||||||
or a model.
|
trace or a model. Commands that report on a database — `info`, `init`, `tag` —
|
||||||
|
print its location, as does an error about a path.
|
||||||
|
|
||||||
Every database in the set is opened with the same embedding configuration. A
|
Every database in the set is opened with the same embedding configuration. A
|
||||||
different `vector_dim` raises `ConfigMismatchError` on open. A different provider
|
different `vector_dim` raises `ConfigMismatchError` on open. A different provider
|
||||||
|
|
|
||||||
|
|
@ -258,8 +258,9 @@ result = await client.analyze("How many documents mention it?", sources=["medic"
|
||||||
A question scoped to some databases can only cite those, and the analysis
|
A question scoped to some databases can only cite those, and the analysis
|
||||||
sandbox mounts only their documents.
|
sandbox mounts only their documents.
|
||||||
|
|
||||||
`sources=None` covers every database the client covers; `sources=[]` covers none
|
`sources=None` covers every database the client covers. `sources=[]` covers
|
||||||
and returns nothing, which is not the same thing.
|
none: `search` returns no results, and `ask` and `analyze` run with no evidence
|
||||||
|
from any database.
|
||||||
|
|
||||||
#### Asking a client what it covers
|
#### Asking a client what it covers
|
||||||
|
|
||||||
|
|
|
||||||
|
|
@ -59,9 +59,8 @@ class HaikuRAGApp:
|
||||||
def _connection(self) -> "tuple[AppConfig, Path]":
|
def _connection(self) -> "tuple[AppConfig, Path]":
|
||||||
"""How to open the one database this command works on, directly.
|
"""How to open the one database this command works on, directly.
|
||||||
|
|
||||||
The configuration a command was given names a *set*; the one it opens
|
Derived per database: opening one of a set against the set's own
|
||||||
needs its own, or a named database behind a URI is opened as the local
|
configuration would reach the local path that stands in for it.
|
||||||
path that stands in for it.
|
|
||||||
"""
|
"""
|
||||||
from haiku.rag.client.session import default_db_path
|
from haiku.rag.client.session import default_db_path
|
||||||
|
|
||||||
|
|
|
||||||
|
|
@ -146,9 +146,8 @@ class DocumentFilterModal(ModalScreen):
|
||||||
filter_list = self.query_one("#filter-list", VerticalScroll)
|
filter_list = self.query_one("#filter-list", VerticalScroll)
|
||||||
await filter_list.remove_children()
|
await filter_list.remove_children()
|
||||||
|
|
||||||
# The page is picked to represent every database; sorting is so it reads
|
# Sort the interleaved page and label each document's database, which
|
||||||
# like a list rather than in whatever order the tables returned. The label
|
# a title alone does not say.
|
||||||
# names the database, since a title alone does not say which one it is in.
|
|
||||||
labelled = sorted(
|
labelled = sorted(
|
||||||
(
|
(
|
||||||
(
|
(
|
||||||
|
|
|
||||||
|
|
@ -133,15 +133,17 @@ class HaikuRAG:
|
||||||
"""Initialize the RAG client with a database path.
|
"""Initialize the RAG client with a database path.
|
||||||
|
|
||||||
Args:
|
Args:
|
||||||
db_path: Path or string path to the database file. If None, uses
|
db_path: Path or string path to the database. When omitted, resolves
|
||||||
config.storage.data_dir.
|
``lancedb.databases``, then ``lancedb.uri``, then the default
|
||||||
|
path under ``storage.data_dir``.
|
||||||
config: Configuration to use. Defaults to the current global config.
|
config: Configuration to use. Defaults to the current global config.
|
||||||
skip_validation: Whether to skip configuration validation on database load.
|
skip_validation: Whether to skip configuration validation on database load.
|
||||||
create: Whether to create the database if it doesn't exist.
|
create: Whether to create the database if it doesn't exist.
|
||||||
read_only: Whether to open the database in read-only mode.
|
read_only: Whether to open the database in read-only mode.
|
||||||
sources: Names from ``config.lancedb.databases`` this client covers.
|
sources: Names from ``config.lancedb.databases`` this client covers,
|
||||||
None means all of them. Ignored when a single ``uri`` or an
|
None for all of them. Only that setting names databases, so a
|
||||||
explicit ``db_path`` is given.
|
name raises when ``lancedb.uri`` placed the database. Ignored
|
||||||
|
when ``db_path`` says which database to open.
|
||||||
"""
|
"""
|
||||||
self._configured = config if config is not None else get_config()
|
self._configured = config if config is not None else get_config()
|
||||||
# What the caller configured, kept intact: entering derives a
|
# What the caller configured, kept intact: entering derives a
|
||||||
|
|
@ -290,14 +292,9 @@ class HaikuRAG:
|
||||||
async def __aenter__(self):
|
async def __aenter__(self):
|
||||||
"""Async context manager entry — initializes store and repositories.
|
"""Async context manager entry — initializes store and repositories.
|
||||||
|
|
||||||
A client borrowing a database is already open and returns itself.
|
A borrowed client reuses its session, which its owner closes. A client
|
||||||
Opening a second session would leak it: teardown declines to close what
|
covering several opens their sessions lazily, so `store` and the
|
||||||
this client did not open.
|
repositories stay unset until one database is named.
|
||||||
|
|
||||||
A client covering several databases opens none of them here: which are
|
|
||||||
searched is a per-query choice, so they open on first use. `store` and the
|
|
||||||
repositories stay unset in that case, since they have no unambiguous
|
|
||||||
meaning across a set.
|
|
||||||
"""
|
"""
|
||||||
if not self._owns_session:
|
if not self._owns_session:
|
||||||
assert self._session is not None
|
assert self._session is not None
|
||||||
|
|
|
||||||
|
|
@ -93,32 +93,27 @@ class SingleDatabaseSession:
|
||||||
create=self._create,
|
create=self._create,
|
||||||
read_only=self.read_only,
|
read_only=self.read_only,
|
||||||
)
|
)
|
||||||
# If _initialize fails mid-way (e.g. migration check raises after
|
# Close a partially initialized store: the caller's `async with`
|
||||||
# connect), close the store so we don't leak the LanceDB connection —
|
# never entered, so its exit will not run.
|
||||||
# the caller's `async with` never entered, so its exit won't run.
|
|
||||||
try:
|
try:
|
||||||
await self.store._initialize()
|
await self.store._initialize()
|
||||||
except BaseException:
|
except BaseException:
|
||||||
self.store.close()
|
self.store.close()
|
||||||
raise
|
raise
|
||||||
except _NAMEABLE_FAILURES as error:
|
except _NAMEABLE_FAILURES as error:
|
||||||
# These say what to run and never where the database is, so the name
|
# These name the remedy and not the database, so the name is added
|
||||||
# is added to the message rather than replacing it: the operator needs
|
# rather than substituted.
|
||||||
# both which database failed and what to do about it.
|
|
||||||
if self.source is None:
|
if self.source is None:
|
||||||
raise
|
raise
|
||||||
raise type(error)(f"database {self.source!r}: {error}") from error
|
raise type(error)(f"database {self.source!r}: {error}") from error
|
||||||
except Exception as error:
|
except Exception as error:
|
||||||
# A legacy `uri` or `db_path` session has no name to report instead,
|
# Without a name there is nothing to report in the location's place.
|
||||||
# so its error passes through as it always has.
|
|
||||||
if self.source is None:
|
if self.source is None:
|
||||||
raise
|
raise
|
||||||
failure = type(error).__name__
|
failure = type(error).__name__
|
||||||
if failure is not None:
|
if failure is not None:
|
||||||
# Raised outside the except block on purpose. A database named in
|
# Raised outside the handler to discard the location-bearing
|
||||||
# config is reported by name, and the original spells out the path or
|
# context, which `from None` would only stop printing.
|
||||||
# the bucket: `from None` would only stop it being *printed*, leaving
|
|
||||||
# it on `__context__` for anything that walks the chain.
|
|
||||||
raise SourceUnavailableError(
|
raise SourceUnavailableError(
|
||||||
f"database {self.source!r} could not be opened: {failure}"
|
f"database {self.source!r} could not be opened: {failure}"
|
||||||
)
|
)
|
||||||
|
|
|
||||||
|
|
@ -247,10 +247,9 @@ class Sandbox:
|
||||||
async def _documents(self) -> "tuple[list[Any], dict[str, HaikuRAG]]":
|
async def _documents(self) -> "tuple[list[Any], dict[str, HaikuRAG]]":
|
||||||
"""Every document in scope, and the client holding each of them.
|
"""Every document in scope, and the client holding each of them.
|
||||||
|
|
||||||
The owners are empty where one connection serves every read: a single
|
Owners are empty where one connection serves every read. The selection
|
||||||
database, or the ephemeral connection opened per read when no client was
|
resolves as a search resolves it, so a database the question excluded
|
||||||
supplied. The selection is resolved the same way a search resolves it, so
|
cannot be mounted.
|
||||||
a database the question excluded cannot be mounted.
|
|
||||||
"""
|
"""
|
||||||
async with self._connection() as rag:
|
async with self._connection() as rag:
|
||||||
if not rag.covers_multiple:
|
if not rag.covers_multiple:
|
||||||
|
|
|
||||||
Loading…
Reference in a new issue