File size: 3,628 Bytes
8c1b9fe
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
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
74
75
76
77
78
79
80
81
82
83
84
85
86
87
88
89
90
91
92
93
94
95
96
97
98
99
100
101
102
103
#!/usr/bin/env python3
"""Reproducible end-to-end Auralynq demo (`make demo`).

Runs the full pipeline locally at $0 with only HUGGINGFACE_TOKEN (optional):
  1. ensure sample data exists (download_data)
  2. build the vector index + knowledge graph
  3. answer a typed question  β†’ grounded, cited answer (fast path)
  4. answer a relational question β†’ routed to PathRAG with evidence paths
  5. run a voice turn on the synthetic audio β†’ speaker/timestamp citations
"""

from __future__ import annotations

from auralynq.config import get_settings
from auralynq.telemetry import configure_logging
from rich.console import Console
from rich.panel import Panel
from rich.table import Table

console = Console()


def _print_answer(title: str, res) -> None:
    console.print(Panel(res.answer or "(no answer)", title=title, border_style="cyan"))
    meta = Table.grid(padding=(0, 2))
    meta.add_row("route", f"[bold]{res.route}[/] ({res.route_confidence})")
    meta.add_row("rationale", res.route_rationale)
    meta.add_row("iterations", str(res.iterations))
    meta.add_row("elapsed_ms", str(res.elapsed_ms))
    console.print(meta)
    if res.citations:
        t = Table(title="Citations", show_lines=False)
        t.add_column("#")
        t.add_column("source")
        t.add_column("locator / timestamp")
        for c in res.citations:
            t.add_row(
                str(c.get("marker", "?")), str(c.get("source", "?")), str(c.get("locator", ""))
            )
        console.print(t)
    if res.path_evidence:
        console.print("[bold]PathRAG evidence paths:[/]")
        for ev in res.path_evidence[:4]:
            console.print(f"  β€’ {' β†’ '.join(ev['nodes'])}  (reliability {ev['reliability']})")


def main() -> None:
    s = get_settings()
    configure_logging(level="WARNING")
    s.ensure_dirs()
    console.rule("[bold cyan]Auralynq β€” Talk to Your Data[/]")

    # 1-2. data + index
    from auralynq.pipeline import build_index

    from scripts.download_data import download

    corpus = s.data_dir / "corpus"
    if not corpus.exists() or not any(corpus.iterdir()):
        console.print("β†’ downloading sample data …")
        download(sample=True)
    console.print("β†’ building index (vector + knowledge graph) …")
    stats = build_index(corpus)
    st = Table(title="Index")
    st.add_column("metric")
    st.add_column("value", justify="right")
    for k, v in stats.items():
        st.add_row(k, str(v))
    console.print(st)

    from auralynq.agent import runner
    from auralynq.agent.runner import answer_question

    runner._CACHE.clear()

    # 3. simple typed question β†’ fast path
    _print_answer("Q1 β€” typed (fast path)", answer_question("What is the capital of France?"))

    # 4. relational question β†’ PathRAG
    _print_answer(
        "Q2 β€” relational (PathRAG)", answer_question("How are Paris, France and Europe related?")
    )

    # 5. voice turn on the synthetic lecture audio
    audio = corpus / "lecture_pathrag.wav"
    if audio.exists():
        from auralynq.voice.loop import run_voice_turn

        console.rule("[bold magenta]Voice turn[/]")
        v = run_voice_turn(audio_path=audio, speak=True)
        console.print(
            Panel(v.transcript or "(no speech)", title="Heard (ASR)", border_style="magenta")
        )
        console.print(Panel(v.answer, title="Spoken answer", border_style="cyan"))
        if v.audio_out_path:
            console.print(f"[green]βœ“[/] TTS audio β†’ {v.audio_out_path} ({v.tts_provider})")

    console.rule("[bold green]Demo complete[/]")


if __name__ == "__main__":
    main()