-
Notifications
You must be signed in to change notification settings - Fork 0
Expand file tree
/
Copy pathcli.py
More file actions
73 lines (55 loc) · 2.39 KB
/
Copy pathcli.py
File metadata and controls
73 lines (55 loc) · 2.39 KB
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
47
48
49
50
51
52
53
54
55
56
57
58
59
60
61
62
63
64
65
66
67
68
69
70
71
72
73
#!/usr/bin/env python3
from __future__ import annotations
from pathlib import Path
import typer
from rich.console import Console
from rich.markdown import Markdown
from rich.panel import Panel
from rich.progress import Progress, SpinnerColumn, TextColumn
app = typer.Typer(name="retrieve-ai", add_completion=False)
console = Console()
def _spinner(label: str) -> Progress:
return Progress(SpinnerColumn(), TextColumn(label), console=console, transient=True)
@app.command()
def ingest(
pdf: Path = typer.Argument(..., help="PDF to ingest."),
force: bool = typer.Option(False, "--force", "-f", help="Re-ingest even if already stored."),
) -> None:
"""Chunk, embed, and store a PDF in the vector database."""
from src.ingestion import ingest as _ingest
with _spinner("Ingesting..."):
collection, added = _ingest(str(pdf), force=force)
if added == 0:
console.print(
f"[yellow]Already ingested.[/] {collection.count()} chunks in '{collection.name}'. "
"Pass --force to re-ingest."
)
else:
console.print(f"[green]Done.[/] Stored {added} chunks in '{collection.name}'.")
@app.command()
def ask(
pdf: Path = typer.Argument(..., help="PDF to query (must already be ingested)."),
question: str = typer.Argument(..., help="Question to answer."),
top_k: int = typer.Option(0, "--top-k", "-k", help="Chunks to retrieve (0 = config default)."),
ingest_first: bool = typer.Option(False, "--ingest", "-i", help="Ingest before asking."),
) -> None:
"""Ask a question against an ingested PDF."""
from src.ingestion import ingest as _ingest, load_collection
from src.workflow import run
if ingest_first:
with _spinner("Ingesting..."):
_ingest(str(pdf))
try:
collection = load_collection(str(pdf))
except Exception:
console.print("[red]Collection not found.[/] Run `ingest` first, or pass --ingest.")
raise typer.Exit(1)
with _spinner("Thinking..."):
answer = run(collection, question, top_k=top_k or None)
console.print(Panel(Markdown(answer.text), title="[bold cyan]Answer[/]", border_style="cyan"))
if answer.citations:
console.print("\n[bold]Sources:[/]")
for i, cit in enumerate(answer.citations, 1):
console.print(f" [dim]{i}.[/] Page {cit['page']} — [italic]{cit['excerpt'][:120]}[/]")
if __name__ == "__main__":
app()