mirror of
https://github.com/semantica-agi/semantica.git
synced 2026-08-30 04:40:16 +00:00
## Summary
Overhaul the CLI and all library modules to produce polished, modern
terminal output comparable to tools like uv, gh, and cargo. Rich was
already a declared dependency but barely used — this commit wires it
throughout every layer.
## Changes by layer
### semantica/cli.py — visual overhaul
- Add imports: `box`, `Panel`, `Rule`, `Syntax`, `Text` from Rich
- Add 7 style constants (`_BRAND`, `_KEY`, `_VAL`, `_DIM`, `_SUCCESS`,
`_WARN_STY`, `_TABLE_BOX`) for a consistent colour palette
- `_ok()` now prefixes output with a green ✓ checkmark
- New `_info()` helper (neutral · bullet, respects --quiet)
- New `_warn()` helper (yellow ⚠ prefix, never suppressed)
- New `_pprint()` helper: renders dicts/lists as syntax-highlighted JSON
(Rich Syntax, monokai theme) instead of raw Python repr; strings
pass through unchanged; respects --quiet
- `info` command: banner replaced with a rounded Rich Panel showing
version + tagline; component table uses SIMPLE_HEAD box
- All 7 table sites updated: `box=SIMPLE_HEAD`, `show_edge=False`,
consistent `_KEY`/`_VAL` column styles (KG Stats, Reasoning Engines,
Recent Decisions, Configured Backends, Backup Info, MCP Tools)
- `_run_build()`: `console.status(spinner="dots")` wraps the blocking
build call; skipped under --quiet / --json
- `parse`, `extract`, `embed generate`, `reason run`, `reason explain`,
`deduplicate`: each wraps its long-running operation in a status
spinner, guarded by --quiet / --json
- All 30+ `console.print(result)` calls replaced with `_pprint()`
- All raw `[yellow]Warning:[/yellow]` and "not running" patterns
replaced with the new `_warn()` / `_WARN_STY` style
### semantica/explorer/__init__.py
- Error messages use `Console(stderr=True)` with `[bold red]Error:[/bold red]`
- Graph loading wrapped in `console.status()` spinner
- Startup info replaced with a cyan-bordered Rich Panel showing URL,
API docs, and health endpoint
### Library internals — replace print() with structured logger calls
All modules below had active `print()` calls that bypassed the logging
framework, corrupted spinners, and polluted stdout in piped/programmatic
use. All replaced with appropriate `self.logger.*` calls:
- `semantica/kg/graph_builder.py` — 23 calls: entity resolution
progress, graph structure steps, GraphStore persistence timing, and
the two `='*60` completion banners → `self.logger.info/debug()`
- `semantica/semantic_extract/methods.py` — 4 verbose-mode debug
prints → `logger.debug()`
- `semantica/semantic_extract/relation_extractor.py` — progress +
error prints → `self.logger.debug/warning()` with `exc_info`
- `semantica/semantic_extract/triplet_extractor.py` — same pattern
- `semantica/semantic_extract/semantic_network_extractor.py` — batch
error prints → `self.logger.warning/error()`
- `semantica/semantic_extract/coreference_resolver.py` — error print
→ `self.logger.error()`
- `semantica/semantic_extract/providers.py` — debug print →
`self.logger.debug()`
### Tooling
- `benchmarks/benchmarks_runner.py`: Rule banner, ✓/✗/⚠ status lines,
Rule separators around regression alert
- `benchmarks/infrastructure/compare.py`: removed manual ANSI escape
codes; comparison output is now a Rich Table with SIMPLE_HEAD;
summary uses coloured Rule + styled SUCCESS/FAILURE messages
- `cookbook/advanced/snowflake_ingestion_examples.py`: `_section()`
helper using Rule; tabular data rendered as Rich Table; result lines
use ✓/✗/⚠ prefixes; logger.error already present, retained
- `docs_check.py`: `pass`/`FAIL` lines use `[bold green]` /
`[bold red]`; summary uses styled output
## Tests
- `tests/test_cli_commands.py`: fix 3 pre-existing mock mismatches
- `test_kg_stats_json_with_mock`: mock now uses `compute_metrics()`
(the method the code actually calls) instead of `get_statistics()`
- `test_dry_run_not_needed_extract_is_read_only` and
`test_stdin_input`: mock now provides `NERExtractor`,
`RelationExtractor`, `TripletExtractor`, `EventDetector`
(the classes the code imports) instead of `SemanticAnalyzer`
Result: 230/230 tests pass (was 227/230)
- `tests/verify_rich_cli.py`: new verification script; exercises all
14 command groups (92 --help checks, table rendering, dry-run
formatting, --json mode, _pprint helper); 111 pass, 0 fail
94 lines
2.8 KiB
Python
94 lines
2.8 KiB
Python
import argparse
|
|
import os
|
|
import subprocess
|
|
import sys
|
|
from datetime import datetime
|
|
|
|
from rich.console import Console
|
|
from rich.rule import Rule
|
|
|
|
console = Console()
|
|
|
|
|
|
def run_benchmarks():
|
|
"""
|
|
Master Runner for Semantica Benchmarks.
|
|
"""
|
|
parser = argparse.ArgumentParser(description="Run Semantica Benchmarks")
|
|
parser.add_argument(
|
|
"--strict", action="store_true", help="Fail script if performance regresses"
|
|
)
|
|
args = parser.parse_args()
|
|
|
|
console.print(Rule("[bold cyan]Semantica Benchmark Suite[/bold cyan]", style="cyan"))
|
|
|
|
timestamp = datetime.now().strftime("%Y%m%d_%H_%M_%S")
|
|
os.makedirs("benchmarks/results", exist_ok=True)
|
|
|
|
current_json = f"benchmarks/results/run_{timestamp}.json"
|
|
baseline_json = "benchmarks/results/baseline.json"
|
|
|
|
cmd = [
|
|
sys.executable,
|
|
"-m",
|
|
"pytest",
|
|
"benchmarks/",
|
|
"-p", "no:typeguard",
|
|
"-p", "no:langsmith",
|
|
"--benchmark-only",
|
|
f"--benchmark-json={current_json}",
|
|
"--benchmark-columns=min,mean,stddev,ops",
|
|
"--benchmark-sort=mean",
|
|
]
|
|
|
|
console.print(f"[dim]Saving results to[/dim] {current_json}")
|
|
result = subprocess.run(cmd)
|
|
|
|
if result.returncode != 0:
|
|
console.print("[bold red] ✗[/bold red] Benchmarks failed to execute (runtime errors).")
|
|
sys.exit(result.returncode)
|
|
|
|
console.print("[bold green] ✓[/bold green] Benchmarks completed execution.")
|
|
|
|
if os.path.exists(baseline_json):
|
|
console.print(f"[dim]Comparing against baseline:[/dim] {baseline_json}")
|
|
|
|
if os.path.exists("benchmarks/infrastructure/compare.py"):
|
|
compare_cmd = [
|
|
sys.executable,
|
|
"benchmarks/infrastructure/compare.py",
|
|
baseline_json,
|
|
current_json,
|
|
]
|
|
|
|
compare_result = subprocess.run(compare_cmd)
|
|
|
|
if compare_result.returncode != 0:
|
|
console.print(Rule(style="red"))
|
|
console.print("[bold red] PERFORMANCE REGRESSION DETECTED[/bold red]")
|
|
console.print(Rule(style="red"))
|
|
if args.strict:
|
|
sys.exit(1)
|
|
else:
|
|
console.print(
|
|
"[bold green] ✓[/bold green] Performance is within acceptable limits."
|
|
)
|
|
else:
|
|
console.print(
|
|
"[bold yellow] ⚠[/bold yellow] Comparison script not found "
|
|
"(benchmarks/infrastructure/compare.py). Skipping comparison."
|
|
)
|
|
else:
|
|
console.print(
|
|
"[bold yellow] ⚠[/bold yellow] No baseline found. "
|
|
"This run effectively sets the new baseline."
|
|
)
|
|
|
|
console.print(
|
|
f"\n[dim]To update baseline:[/dim] cp {current_json} {baseline_json}"
|
|
)
|
|
|
|
|
|
if __name__ == "__main__":
|
|
run_benchmarks()
|