diff --git a/docs/agents.md b/docs/agents.md index 376ac14d..4d218383 100644 --- a/docs/agents.md +++ b/docs/agents.md @@ -229,6 +229,20 @@ async with HaikuRAG(path_to_db) as client: print(report.executive_summary) ``` +### Filtering Documents + +Both Research and Deep QA graphs support restricting searches to specific documents via the `search_filter` parameter. Set it to a SQL WHERE clause before running: + +```python +state = ResearchState.from_config(context=context, config=Config) +# Only search documents with these IDs +state.search_filter = "id IN ('doc-123', 'doc-456')" + +result = await graph.run(state=state, deps=deps) +``` + +The filter applies to all search operations in the graph (context gathering and sub-question searches). See [Filtering Search Results](python.md#filtering-search-results) for available filter columns and syntax. + Alternative usage with custom config: ```python diff --git a/docs/cli.md b/docs/cli.md index 1d432f7d..a1207ef4 100644 --- a/docs/cli.md +++ b/docs/cli.md @@ -149,8 +149,19 @@ Show verbose output with deep QA: haiku-rag ask "What are the main features and architecture of haiku.rag?" --deep --verbose ``` -The QA agent will search your documents for relevant information and provide a comprehensive answer. With `--cite`, responses include citations showing which documents were used. With `--deep`, the question is decomposed into sub-questions that are answered in parallel before synthesizing a final answer. With `--verbose` (only with `--deep`), you'll see the planning, searching, evaluation, and synthesis steps as they happen. -When available, citations use the document title; otherwise they fall back to the URI. +Filter to specific documents with deep QA: +```bash +haiku-rag ask "What are the main findings?" --deep --filter "uri LIKE '%paper%'" +``` + +The QA agent searches your documents for relevant information and provides a comprehensive answer. When available, citations use the document title; otherwise they fall back to the URI. + +Flags: + +- `--cite`: Include citations showing which documents were used +- `--deep`: Decompose the question into sub-questions answered in parallel before synthesizing a final answer +- `--verbose`: Show planning, searching, evaluation, and synthesis steps (only with `--deep`) +- `--filter`: Restrict searches to documents matching the filter (only with `--deep`) ## Research @@ -166,8 +177,16 @@ With verbose output to see progress: haiku-rag research "How does haiku.rag organize and query documents?" --verbose ``` +Filter to specific documents: + +```bash +haiku-rag research "What are the key findings?" --filter "uri LIKE '%paper%'" +``` + Flags: + - `--verbose`: Show planning, searching previews, evaluation summary, and stop reason +- `--filter`: SQL WHERE clause to filter documents (see [Filtering Search Results](python.md#filtering-search-results)) Research parameters like `max_iterations`, `confidence_threshold`, and `max_concurrency` are configured in your [configuration file](configuration/index.md) under the `research` section. diff --git a/haiku_rag_slim/haiku/rag/app.py b/haiku_rag_slim/haiku/rag/app.py index 37d87eac..c92206f4 100644 --- a/haiku_rag_slim/haiku/rag/app.py +++ b/haiku_rag_slim/haiku/rag/app.py @@ -314,6 +314,7 @@ class HaikuRAGApp: cite: bool = False, deep: bool = False, verbose: bool = False, + filter: str | None = None, ): """Ask a question using the RAG system. @@ -322,6 +323,7 @@ class HaikuRAGApp: cite: Include citations in the answer deep: Use deep QA mode (multi-step reasoning) verbose: Show verbose output + filter: SQL WHERE clause to filter documents """ async with HaikuRAG(db_path=self.db_path, config=self.config) as self.client: try: @@ -334,6 +336,7 @@ class HaikuRAGApp: graph = build_deep_qa_graph(config=self.config) context = DeepQAContext(original_question=question) state = DeepQAState.from_config(context=context, config=self.config) + state.search_filter = filter deps = DeepQADeps(client=self.client) if verbose: @@ -371,12 +374,15 @@ class HaikuRAGApp: except Exception as e: self.console.print(f"[red]Error: {e}[/red]") - async def research(self, question: str, verbose: bool = False): + async def research( + self, question: str, verbose: bool = False, filter: str | None = None + ): """Run research via the pydantic-graph pipeline. Args: question: The research question verbose: Show AG-UI event stream during execution + filter: SQL WHERE clause to filter documents """ async with HaikuRAG(db_path=self.db_path, config=self.config) as client: try: @@ -387,6 +393,7 @@ class HaikuRAGApp: graph = build_research_graph(config=self.config) context = ResearchContext(original_question=question) state = ResearchState.from_config(context=context, config=self.config) + state.search_filter = filter deps = ResearchDeps(client=client) if verbose: diff --git a/haiku_rag_slim/haiku/rag/cli.py b/haiku_rag_slim/haiku/rag/cli.py index b22fa1f8..84216409 100644 --- a/haiku_rag_slim/haiku/rag/cli.py +++ b/haiku_rag_slim/haiku/rag/cli.py @@ -305,9 +305,17 @@ def ask( "--verbose", help="Show verbose progress output (only with --deep)", ), + filter: str | None = typer.Option( + None, + "--filter", + "-f", + help="SQL WHERE clause to filter documents (only with --deep)", + ), ): app = create_app(db) - asyncio.run(app.ask(question=question, cite=cite, deep=deep, verbose=verbose)) + asyncio.run( + app.ask(question=question, cite=cite, deep=deep, verbose=verbose, filter=filter) + ) @cli.command("research", help="Run multi-agent research and output a concise report") @@ -325,9 +333,15 @@ def research( "--verbose", help="Show planning, searching previews, evaluation summary, and stop reason", ), + filter: str | None = typer.Option( + None, + "--filter", + "-f", + help="SQL WHERE clause to filter documents (e.g., \"uri LIKE '%arxiv%'\")", + ), ): app = create_app(db) - asyncio.run(app.research(question=question, verbose=verbose)) + asyncio.run(app.research(question=question, verbose=verbose, filter=filter)) @cli.command("settings", help="Display current configuration settings")