Skip to content

Commit 9a915c9

Browse files
authored
Merge pull request #123 from Ar9av/feat/graphrag-query
feat(graphrag): graph-index query pre-pass eliminates speculative page reads
2 parents 0221e0d + a7fb1d6 commit 9a915c9

4 files changed

Lines changed: 693 additions & 0 deletions

File tree

.skills/wiki-query/SKILL.md

Lines changed: 25 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -56,6 +56,31 @@ In filtered mode, note the filter in the Step 6 log entry: `mode=filtered`.
5656

5757
**Follow the Retrieval Primitives table in `llm-wiki/SKILL.md`.** Reading is the dominant cost of this skill — use the cheapest primitive that answers the question and escalate only when it can't. Never jump straight to full-page reads.
5858

59+
### Step 0: GraphRAG Pre-pass (fast index query — no page reads)
60+
61+
Before opening any pages, query the compiled graph index:
62+
63+
```bash
64+
obsidian-wiki graph-query "$OBSIDIAN_VAULT_PATH" "<question>" --pretty
65+
```
66+
67+
Output fields:
68+
69+
- **`answer_type`**: `direct` | `path` | `list` | `gap` — shapes what to do next
70+
- **`candidates`**: top-ranked pages by title/tag/summary match + degree, with scores and summaries
71+
- **`should_read`**: the pages most worth opening — start here instead of speculatively reading many files
72+
- **`path`**: for multi-hop queries, the shortest wikilink path between the two concepts
73+
- **`god_nodes_relevant`**: hub pages related to your query terms — always useful context
74+
- **`index_only`**: if `true`, the top candidate's summary already answers the question — skip page reads
75+
76+
**Decision tree:**
77+
78+
1. If `index_only: true` → answer directly from `candidates[0].summary`. Skip Steps 1–4, go to Step 5.
79+
2. If `answer_type == "path"` and `path` is non-empty → the connection is in `path`. Read only those pages.
80+
3. Otherwise → open only `should_read` pages (not all candidates). This replaces the speculative 5–10 page reads the old flow required.
81+
82+
**Fallback** (if `obsidian-wiki` is not installed): proceed with Step 1 as normal using grep and index.md.
83+
5984
### Step 1: Understand the Question
6085

6186
Classify the query type:

obsidian_wiki/cli.py

Lines changed: 25 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -349,6 +349,20 @@ def cmd_setup(args: argparse.Namespace) -> int:
349349
return 0
350350

351351

352+
def cmd_graph_query(args: argparse.Namespace) -> int:
353+
from obsidian_wiki.graphrag import query
354+
vault = Path(args.vault).expanduser().resolve()
355+
if not vault.is_dir():
356+
print(f"error: vault not found: {vault}", file=sys.stderr)
357+
return 1
358+
result = query(vault, args.question, top_n=args.top, max_should_read=args.max_read)
359+
if args.pretty:
360+
print(json.dumps(result, indent=2))
361+
else:
362+
print(json.dumps(result))
363+
return 0
364+
365+
352366
def cmd_batch_plan(args: argparse.Namespace) -> int:
353367
from obsidian_wiki.batch import plan_batches
354368
source_dir = Path(args.source_dir).expanduser().resolve()
@@ -491,6 +505,17 @@ def build_parser() -> argparse.ArgumentParser:
491505
ip = sub.add_parser("info", help="show install paths, version, and config")
492506
ip.set_defaults(func=cmd_info)
493507

508+
gq = sub.add_parser(
509+
"graph-query",
510+
help="answer a question from the vault's wikilink index without reading page bodies",
511+
)
512+
gq.add_argument("vault", help="path to the Obsidian vault")
513+
gq.add_argument("question", help="question to answer")
514+
gq.add_argument("--top", type=int, default=8, help="number of candidate pages to rank (default: 8)")
515+
gq.add_argument("--max-read", type=int, default=3, help="max pages to return in should_read (default: 3)")
516+
gq.add_argument("--pretty", action="store_true", help="pretty-print JSON output")
517+
gq.set_defaults(func=cmd_graph_query)
518+
494519
bp = sub.add_parser(
495520
"batch-plan",
496521
help="split a source directory into parallel-ingest batches, skipping unchanged files",

0 commit comments

Comments
 (0)