Say what reader_for and an empty sources mean
`reader_for` documented None as covering any database it could not place, but a name outside the set raises `KeyError` like `clients_for` does: provenance naming a database this client does not cover is wrong rather than absent. None means one thing, a federated client given no name. `sources=[]` means two things. On a search it selects nothing to search; on the constructor it raises, since a client over no database can do nothing. Both are written down now. A capability reads through a lent client, so what a citation records is that client's database and not the scope the capability was built with. Chat lends one, and had no test saying so.
This commit is contained in:
parent
474245ab59
commit
45a5e68da5
3 changed files with 47 additions and 4 deletions
|
|
@ -261,6 +261,9 @@ their documents.
|
|||
none: `search` returns no results, and `ask` and `analyze` run with no evidence
|
||||
from any database.
|
||||
|
||||
On the constructor, `sources=[]` raises `ValueError` instead. A selection of
|
||||
nothing to search is a legitimate question; a client over no database is not.
|
||||
|
||||
#### Inspecting the client scope
|
||||
|
||||
```python
|
||||
|
|
|
|||
|
|
@ -143,7 +143,9 @@ class HaikuRAG:
|
|||
sources: Names from ``config.lancedb.databases`` this client covers,
|
||||
None for all of them. Only that setting names databases, so a
|
||||
name raises when ``lancedb.uri`` placed the database. Ignored
|
||||
when ``db_path`` says which database to open.
|
||||
when ``db_path`` says which database to open. ``[]`` raises: a
|
||||
client over no database can do nothing, unlike ``sources=[]`` on
|
||||
a search, which is a selection of nothing to search.
|
||||
"""
|
||||
self._configured = config if config is not None else get_config()
|
||||
# What the caller configured, kept intact: entering derives a
|
||||
|
|
@ -195,9 +197,10 @@ class HaikuRAG:
|
|||
"""The client that can read `source` — itself, where it reads one
|
||||
database.
|
||||
|
||||
None where the database cannot be placed: a client covering a set needs
|
||||
the name, and evidence recorded before databases could be named carries
|
||||
none.
|
||||
None only when a client covering a set is given no name, as for evidence
|
||||
recorded before databases could be named. A name outside the set raises
|
||||
`KeyError`, the same as `clients_for`: provenance naming a database this
|
||||
client does not cover is wrong rather than absent.
|
||||
"""
|
||||
if not self.covers_multiple:
|
||||
return self
|
||||
|
|
|
|||
|
|
@ -7,6 +7,7 @@ import pytest
|
|||
from haiku.rag.capabilities._tools import search_corpus
|
||||
from haiku.rag.capabilities.rag import RAGState, create_capability
|
||||
from haiku.rag.client import HaikuRAG
|
||||
from haiku.rag.client.scope import DatabaseScope
|
||||
from haiku.rag.sandbox import AnalysisContext, Sandbox
|
||||
from haiku.rag.store.models import SearchResult
|
||||
from tests.multi_db.helpers import (
|
||||
|
|
@ -199,6 +200,42 @@ class TestCollectionIdentityForTheModel:
|
|||
assert result.stdout.count("['alpha', 'beta']") == 2
|
||||
|
||||
|
||||
class TestLendingANamedClient:
|
||||
@pytest.mark.asyncio
|
||||
async def test_a_lent_named_client_names_the_citation(self, tmp_path):
|
||||
"""The chat TUI builds capabilities before its client exists and lends
|
||||
it on mount, so what a citation records is the lent client's database
|
||||
and not whatever scope the capability was constructed with."""
|
||||
from tests.capabilities.test_capabilities import Deps, make_context
|
||||
|
||||
config = _config(tmp_path, ["alpha", "beta"])
|
||||
await _seed(config, "alpha", ["alpha document about cats"])
|
||||
await _seed(config, "beta", ["beta document about cats"])
|
||||
|
||||
# `run_chat` derives these for a single-database scope.
|
||||
scope = DatabaseScope.resolve(config, database_name="alpha")
|
||||
one_config, one_path = scope.databases[0].connection(config)
|
||||
capability = create_capability(
|
||||
db_path=one_path, config=one_config, defer_loading=False
|
||||
)
|
||||
|
||||
async with HaikuRAG(config=config, sources=["alpha"]) as client:
|
||||
# What `ChatApp.on_mount` does.
|
||||
capability.borrowed_rag = client
|
||||
deps = Deps(state={"rag": RAGState().model_dump(mode="json")})
|
||||
run = await capability.for_run(make_context(deps))
|
||||
assert run.state is not None
|
||||
await run._search("cats", limit=5)
|
||||
[result] = run.state.searches["cats"]
|
||||
assert result.chunk_id is not None
|
||||
await run._cite([result.chunk_id])
|
||||
|
||||
[citation] = run.state.citation_index.values()
|
||||
|
||||
assert result.source == "alpha"
|
||||
assert citation.source == "alpha"
|
||||
|
||||
|
||||
class TestWhenTheModelIsToldTheCollection:
|
||||
"""The line is decided by what the search spans, not by whether a name
|
||||
exists: one collection has nothing to distinguish."""
|
||||
|
|
|
|||
Loading…
Reference in a new issue