Drop the indirection around what a client covers
`covers_several_databases` had one line of body and two call sites. `_db_path_given` guarded a default path manufactured in `__init__` and overwritten in `__aenter__`; `_requested_db_path` is what the caller asked for, and the effective path falls out of the resolved scope.
This commit is contained in:
parent
1b3334b5af
commit
4c2bfc4fc1
6 changed files with 15 additions and 35 deletions
|
|
@ -131,17 +131,6 @@ class EvidenceState(BaseModel):
|
||||||
self.searches.clear()
|
self.searches.clear()
|
||||||
|
|
||||||
|
|
||||||
def covers_several_databases(scope: DatabaseScope, rag: "HaikuRAG | None") -> bool:
|
|
||||||
"""Whether the capability will read from more than one database.
|
|
||||||
|
|
||||||
A lent client already covers what it covers; otherwise the scope says.
|
|
||||||
Instructions follow coverage, not configuration.
|
|
||||||
"""
|
|
||||||
if rag is not None:
|
|
||||||
return rag.covers_multiple
|
|
||||||
return scope.covers_multiple
|
|
||||||
|
|
||||||
|
|
||||||
def _awaits_the_model(messages: list[ModelMessage]) -> bool:
|
def _awaits_the_model(messages: list[ModelMessage]) -> bool:
|
||||||
"""Whether the history unmistakably leaves the model something to answer.
|
"""Whether the history unmistakably leaves the model something to answer.
|
||||||
|
|
||||||
|
|
@ -637,6 +626,5 @@ class RAGCapabilityBase[StateT: EvidenceState](AbstractCapability[Any]):
|
||||||
__all__ = [
|
__all__ = [
|
||||||
"CodeExecutionEntry",
|
"CodeExecutionEntry",
|
||||||
"RAGCapabilityBase",
|
"RAGCapabilityBase",
|
||||||
"covers_several_databases",
|
|
||||||
"resolve_scope",
|
"resolve_scope",
|
||||||
]
|
]
|
||||||
|
|
|
||||||
|
|
@ -15,7 +15,6 @@ from haiku.rag.capabilities._base import (
|
||||||
CodeExecutionEntry,
|
CodeExecutionEntry,
|
||||||
EvidenceState,
|
EvidenceState,
|
||||||
RAGCapabilityBase,
|
RAGCapabilityBase,
|
||||||
covers_several_databases,
|
|
||||||
resolve_scope,
|
resolve_scope,
|
||||||
)
|
)
|
||||||
from haiku.rag.capabilities._tools import merge_results
|
from haiku.rag.capabilities._tools import merge_results
|
||||||
|
|
@ -215,7 +214,9 @@ def create_capability(
|
||||||
analysis_model = config.analysis.model or config.qa.model
|
analysis_model = config.analysis.model or config.qa.model
|
||||||
scope = resolve_scope(db_path, config)
|
scope = resolve_scope(db_path, config)
|
||||||
instruction_text = instructions()
|
instruction_text = instructions()
|
||||||
if covers_several_databases(scope, rag):
|
# A lent client covers what it covers; otherwise the scope says.
|
||||||
|
several = rag.covers_multiple if rag is not None else scope.covers_multiple
|
||||||
|
if several:
|
||||||
instruction_text += several_databases_instructions()
|
instruction_text += several_databases_instructions()
|
||||||
return AnalysisCapability(
|
return AnalysisCapability(
|
||||||
scope=scope,
|
scope=scope,
|
||||||
|
|
|
||||||
|
|
@ -13,7 +13,6 @@ if TYPE_CHECKING:
|
||||||
from haiku.rag.capabilities._base import (
|
from haiku.rag.capabilities._base import (
|
||||||
EvidenceState,
|
EvidenceState,
|
||||||
RAGCapabilityBase,
|
RAGCapabilityBase,
|
||||||
covers_several_databases,
|
|
||||||
resolve_scope,
|
resolve_scope,
|
||||||
)
|
)
|
||||||
from haiku.rag.config.models import AppConfig
|
from haiku.rag.config.models import AppConfig
|
||||||
|
|
@ -118,7 +117,9 @@ def create_capability(
|
||||||
config = get_config()
|
config = get_config()
|
||||||
scope = resolve_scope(db_path, config)
|
scope = resolve_scope(db_path, config)
|
||||||
instruction_text = instructions()
|
instruction_text = instructions()
|
||||||
if covers_several_databases(scope, rag):
|
# A lent client covers what it covers; otherwise the scope says.
|
||||||
|
several = rag.covers_multiple if rag is not None else scope.covers_multiple
|
||||||
|
if several:
|
||||||
instruction_text += several_databases_instructions()
|
instruction_text += several_databases_instructions()
|
||||||
return RAGCapability(
|
return RAGCapability(
|
||||||
scope=scope,
|
scope=scope,
|
||||||
|
|
|
||||||
|
|
@ -148,11 +148,7 @@ class HaikuRAG:
|
||||||
# single-database configuration from it, and asking again has to see the
|
# single-database configuration from it, and asking again has to see the
|
||||||
# same set rather than the answer from last time.
|
# same set rather than the answer from last time.
|
||||||
self._config = self._configured
|
self._config = self._configured
|
||||||
self._db_path_given = db_path is not None
|
self._requested_db_path = Path(db_path) if db_path is not None else None
|
||||||
if db_path is None:
|
|
||||||
db_path = self._config.storage.data_dir / "haiku.rag.lancedb"
|
|
||||||
|
|
||||||
self._db_path = db_path
|
|
||||||
self._skip_validation = skip_validation
|
self._skip_validation = skip_validation
|
||||||
self._create = create
|
self._create = create
|
||||||
self._read_only = read_only
|
self._read_only = read_only
|
||||||
|
|
@ -285,10 +281,9 @@ class HaikuRAG:
|
||||||
if self._scope is not None:
|
if self._scope is not None:
|
||||||
return self._scope
|
return self._scope
|
||||||
scope = DatabaseScope.resolve(
|
scope = DatabaseScope.resolve(
|
||||||
self._configured,
|
self._configured, database_path=self._requested_db_path
|
||||||
database_path=self._db_path if self._db_path_given else None,
|
|
||||||
)
|
)
|
||||||
if self._requested_sources is not None and not self._db_path_given:
|
if self._requested_sources is not None and self._requested_db_path is None:
|
||||||
scope = scope.select(self._requested_sources)
|
scope = scope.select(self._requested_sources)
|
||||||
return scope
|
return scope
|
||||||
|
|
||||||
|
|
@ -326,12 +321,9 @@ class HaikuRAG:
|
||||||
|
|
||||||
[ref] = scope.databases
|
[ref] = scope.databases
|
||||||
self._config, db_path = ref.connection(self._configured)
|
self._config, db_path = ref.connection(self._configured)
|
||||||
self._db_path = (
|
|
||||||
db_path if db_path is not None else default_db_path(self._config)
|
|
||||||
)
|
|
||||||
|
|
||||||
self._session = await SingleDatabaseSession(
|
self._session = await SingleDatabaseSession(
|
||||||
self._db_path,
|
db_path if db_path is not None else default_db_path(self._config),
|
||||||
self._config,
|
self._config,
|
||||||
skip_validation=self._skip_validation,
|
skip_validation=self._skip_validation,
|
||||||
create=self._create,
|
create=self._create,
|
||||||
|
|
|
||||||
|
|
@ -117,12 +117,10 @@ SearchType = Literal["vector", "fts", "hybrid"]
|
||||||
|
|
||||||
|
|
||||||
def qualified_id(source: str | None, id: str | None) -> tuple[str | None, str | None]:
|
def qualified_id(source: str | None, id: str | None) -> tuple[str | None, str | None]:
|
||||||
"""What tells one chunk from another: a chunk id is unique within a database
|
"""What tells one chunk from another: an id is unique within a database only.
|
||||||
and says nothing across them.
|
|
||||||
|
|
||||||
For in-memory structures only. Everything serialized records the id alone
|
For in-memory structures. Serialized ones record the id alone and reject
|
||||||
and rejects ambiguity instead. `id` is optional, and results built by hand
|
ambiguity instead. Results built by hand carry no id and cannot be told apart.
|
||||||
carry none and cannot be told apart.
|
|
||||||
"""
|
"""
|
||||||
return (source, id)
|
return (source, id)
|
||||||
|
|
||||||
|
|
|
||||||
|
|
@ -53,9 +53,9 @@ def test_default_db_path_comes_from_storage_data_dir(tmp_path):
|
||||||
config = AppConfig()
|
config = AppConfig()
|
||||||
config.storage.data_dir = tmp_path
|
config.storage.data_dir = tmp_path
|
||||||
|
|
||||||
client = HaikuRAG(config=config)
|
[ref] = HaikuRAG(config=config)._resolve_scope().databases
|
||||||
|
|
||||||
assert client._db_path == tmp_path / "haiku.rag.lancedb"
|
assert ref.db_path == tmp_path / "haiku.rag.lancedb"
|
||||||
|
|
||||||
|
|
||||||
@pytest.mark.asyncio
|
@pytest.mark.asyncio
|
||||||
|
|
|
||||||
Loading…
Reference in a new issue