Chat answers with the same capabilities `ask` does, so it federates as naturally as `ask` and `analyze` — but it went through the one-database guard and refused a configured set outright, which left no way to chat across several databases. The guard was the visible half. `run_chat` also defaulted `db_path` to the single default path whenever it was None, so lifting the refusal alone would still have opened one database. It now leaves the path unresolved when `lancedb.databases` names the set, and the client resolves it. Listing and counting documents fan out over the set, which is what the document filter reads, and visual grounding resolves the database holding the cited chunk through the citation's source: chunks, pages and bounding boxes all come from that one database. A limit on a listing means that many documents in total, not that many per database. The info modal reports every database it covers, each under its configured name and without its location, since names are the only identity that leaves the configuration. `database_lines` is what one database reports about itself, shared by both paths, and it reports a failure as a line so one unreachable database does not cost the report on the others. `inspect` stays a one-database command. It browses one database's documents and chunks, so a set has nothing to show it.
80 lines
2.5 KiB
Python
80 lines
2.5 KiB
Python
from pathlib import Path
|
|
|
|
|
|
def run_chat(
|
|
db_path: Path | None = None,
|
|
read_only: bool = False,
|
|
model: str | None = None,
|
|
capabilities: list[str] | None = None,
|
|
) -> None:
|
|
"""Run the chat TUI.
|
|
|
|
Args:
|
|
db_path: Path to the LanceDB database. If None, uses default from config.
|
|
read_only: Whether to open the database in read-only mode.
|
|
model: Model to use for the chat.
|
|
capabilities: Capabilities to enable ("rag", "analysis"). Defaults to ["rag"].
|
|
"""
|
|
try:
|
|
from haiku.rag.chat.app import ChatApp
|
|
except ImportError as e:
|
|
raise ImportError(
|
|
"textual is not installed. Please install it with `pip install 'haiku.rag-slim[tui]'` or use the full haiku.rag package."
|
|
) from e
|
|
|
|
from haiku.rag.config import get_config
|
|
from haiku.rag.utils import get_model, parse_model_option
|
|
|
|
config = get_config()
|
|
if db_path is None and not config.lancedb.databases:
|
|
db_path = config.storage.data_dir / "haiku.rag.lancedb"
|
|
|
|
if model:
|
|
model_config = parse_model_option(model)
|
|
config.qa.model = model_config
|
|
config.analysis.model = model_config
|
|
|
|
enabled = capabilities or ["rag"]
|
|
capability_list = []
|
|
defer_loading = len(enabled) > 1
|
|
|
|
# One agent drives every attached capability, so a capability's
|
|
# image-attachment gate must track that single model: analysis.model only
|
|
# when analysis runs alone, otherwise qa.model. Passing it to every
|
|
# capability keeps their vision flag aligned with the model actually running.
|
|
if "rag" not in enabled and "analysis" in enabled:
|
|
driving_model = config.analysis.model or config.qa.model
|
|
else:
|
|
driving_model = config.qa.model
|
|
|
|
if "rag" in enabled:
|
|
from haiku.rag.capabilities.rag import create_capability
|
|
|
|
capability_list.append(
|
|
create_capability(
|
|
db_path=db_path,
|
|
config=config,
|
|
defer_loading=defer_loading,
|
|
vision=driving_model.vision,
|
|
)
|
|
)
|
|
|
|
if "analysis" in enabled:
|
|
from haiku.rag.capabilities.analysis import create_capability
|
|
|
|
capability_list.append(
|
|
create_capability(
|
|
db_path=db_path,
|
|
config=config,
|
|
defer_loading=defer_loading,
|
|
vision=driving_model.vision,
|
|
)
|
|
)
|
|
|
|
app = ChatApp(
|
|
db_path,
|
|
capabilities=capability_list,
|
|
read_only=read_only,
|
|
model=model or get_model(driving_model, config),
|
|
)
|
|
app.run()
|