-
Notifications
You must be signed in to change notification settings - Fork 0
Expand file tree
/
Copy pathcli.py
More file actions
149 lines (117 loc) · 4.64 KB
/
Copy pathcli.py
File metadata and controls
149 lines (117 loc) · 4.64 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
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
104
105
106
107
108
109
110
111
112
113
114
115
116
117
118
119
120
121
122
123
124
125
126
127
128
129
130
131
132
133
134
135
136
137
138
139
140
141
142
143
144
145
146
147
148
149
"""Command Line Interface (CLI) for Epistemic Forge.
Provides a rich, self-explanatory terminal experience showing the Neuro-Symbolic
reasoning process in real-time, without overwhelming the user with raw JSON.
"""
from __future__ import annotations
import argparse
import sys
from rich.console import Console
from rich.panel import Panel
from rich.progress import Progress, SpinnerColumn, TextColumn
from rich.tree import Tree
from epistemic_forge.memory.economy import budget_manager
from epistemic_forge.models import ProjectSpec
from epistemic_forge.pipeline.arsenal_run import run_pipeline
console = Console()
def build_parser() -> argparse.ArgumentParser:
"""Constructs the argument parser with standard and Hermes-routing overrides."""
parser = argparse.ArgumentParser(
prog="epistemic-forge",
description="Neuro-Symbolic Agent Framework for deterministic reasoning.",
)
# Core Epistemic Arguments
parser.add_argument("--title", required=True, help="Project title or theme.")
parser.add_argument(
"--question", required=True, help="The core research or dialectic question."
)
parser.add_argument(
"--domain",
default="hybrid",
help="Reasoning domain (research, philosophy, etc.)",
)
# Hermes Routing Arguments (Omni-Provider)
parser.add_argument(
"--model",
default="gpt-4o-mini",
help="Provider/Model string (e.g., 'anthropic/claude-3-sonnet').",
)
parser.add_argument(
"--api-base", default=None, help="Custom API Base URL (for Local/vLLM/Ollama)."
)
return parser
def display_claim_lattice(claims: list):
"""Renders the parsed Claim Lattice as a visual Tree in the terminal."""
if not claims:
return
tree = Tree("🌳 [bold blue]Epistemic Claim Lattice[/bold blue]")
for claim in claims:
# Pydantic model dump compatibility
c_dict = claim.model_dump() if hasattr(claim, "model_dump") else claim
claim_node = tree.add(
f"[bold white]Claim:[/bold white] {c_dict.get('text', 'Unknown')}"
)
if c_dict.get("support"):
support_node = claim_node.add("[green]Supports[/green]")
for s in c_dict["support"]:
support_node.add(f"✓ {s}")
if c_dict.get("objections"):
obj_node = claim_node.add("[red]Objections[/red]")
for o in c_dict["objections"]:
obj_node.add(f"✗ {o}")
console.print(Panel(tree, title="Final Cognitive Structure", border_style="blue"))
def main():
"""Main entrypoint for the CLI."""
parser = build_parser()
args = parser.parse_args()
console.print(
"\n[bold magenta]🧠 Epistemic Forge[/bold magenta] — Initializing Neuro-Symbolic Pipeline"
)
console.print(f"[dim]Routing to model: {args.model}[/dim]\n")
spec = ProjectSpec(
title=args.title,
question=args.question,
domain=args.domain,
target_model=args.model,
budget_tokens=8000,
api_base=args.api_base,
)
try:
# Use Rich Progress bar to show deterministic orchestration
with Progress(
SpinnerColumn(),
TextColumn("[progress.description]{task.description}"),
transient=True,
) as progress:
task = progress.add_task(
"[cyan]L2 Conductor is dispatching semantic experts...", total=None
)
# Execute the core pipeline (Hermes routing overrides are passed through)
result = run_pipeline(
title=spec.title,
question=spec.question,
domain=spec.domain.value,
target_model=args.model,
api_base=args.api_base,
)
progress.update(
task,
description="[green]Synthesis complete. Crystallizing lattice...[/green]",
)
# Render output
console.print("[bold green]✔ Pipeline Execution Successful.[/bold green]\n")
if hasattr(result, "claims") and result.claims:
display_claim_lattice(result.claims)
else:
console.print(
"[yellow]Notice: No claims extracted in the final result.[/yellow]"
)
# SOTA EXPORT
from epistemic_forge.io.export import export_result
export_dir = f'runs/{spec.title.replace(" ", "_").lower()}'
export_result(result, export_dir)
console.print(f"\n[bold yellow]💰 {budget_manager.get_report()}[/bold yellow]")
except Exception:
console.print_exception(show_locals=True)
sys.exit(1)
if __name__ == "__main__":
main()