Upload aco/cli.py with huggingface_hub
Browse files- aco/cli.py +98 -108
aco/cli.py
CHANGED
|
@@ -1,123 +1,113 @@
|
|
| 1 |
-
"""CLI for Agent Cost Optimizer."""
|
| 2 |
-
|
| 3 |
-
|
| 4 |
-
import
|
| 5 |
-
import sys
|
| 6 |
-
from pathlib import Path
|
| 7 |
-
|
| 8 |
-
from aco.optimizer import AgentCostOptimizer
|
| 9 |
from aco.config import ACOConfig
|
| 10 |
-
from aco.
|
| 11 |
-
|
| 12 |
|
| 13 |
def main():
|
| 14 |
-
parser = argparse.ArgumentParser(description="Agent Cost Optimizer")
|
| 15 |
-
|
| 16 |
-
|
| 17 |
-
|
| 18 |
-
|
| 19 |
-
|
| 20 |
-
|
| 21 |
-
|
| 22 |
-
|
| 23 |
-
|
| 24 |
-
|
| 25 |
-
|
| 26 |
-
|
| 27 |
-
|
| 28 |
-
|
| 29 |
-
|
| 30 |
-
|
| 31 |
-
|
| 32 |
-
|
| 33 |
-
|
| 34 |
-
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
| 35 |
args = parser.parse_args()
|
| 36 |
-
|
| 37 |
-
if args.command == "optimize":
|
| 38 |
-
_cmd_optimize(args)
|
| 39 |
-
elif args.command == "benchmark":
|
| 40 |
-
_cmd_benchmark(args)
|
| 41 |
-
elif args.command == "report":
|
| 42 |
-
_cmd_report(args)
|
| 43 |
-
else:
|
| 44 |
parser.print_help()
|
| 45 |
-
|
|
|
|
|
|
|
| 46 |
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
| 47 |
|
| 48 |
-
|
| 49 |
-
|
| 50 |
-
|
| 51 |
-
|
| 52 |
-
|
| 53 |
-
|
| 54 |
-
|
| 55 |
-
|
| 56 |
-
|
| 57 |
-
|
| 58 |
-
|
| 59 |
-
|
| 60 |
-
|
| 61 |
-
"tool_decisions": [
|
| 62 |
-
{"tool": d.tool_name, "decision": d.decision.value, "cost": d.estimated_cost}
|
| 63 |
-
for d in result.tool_decisions
|
| 64 |
-
],
|
| 65 |
-
"verifier": result.verifier_decision.decision.value if result.verifier_decision else None,
|
| 66 |
-
"doom_score": result.doom_assessment.confidence if result.doom_assessment else None,
|
| 67 |
-
"meta_tool_match": result.meta_tool_match is not None,
|
| 68 |
-
}
|
| 69 |
-
|
| 70 |
-
json_str = json.dumps(output, indent=2)
|
| 71 |
-
if args.output == "-":
|
| 72 |
-
print(json_str)
|
| 73 |
-
else:
|
| 74 |
-
with open(args.output, "w") as f:
|
| 75 |
-
f.write(json_str)
|
| 76 |
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
| 77 |
|
| 78 |
-
|
| 79 |
-
|
| 80 |
-
|
| 81 |
-
|
| 82 |
-
|
| 83 |
-
|
| 84 |
-
|
| 85 |
-
|
| 86 |
-
|
| 87 |
-
|
| 88 |
-
if args.ablations:
|
| 89 |
-
print("Running ablations...")
|
| 90 |
-
ablation_results = suite.run_ablations(traces)
|
| 91 |
-
results.update(ablation_results)
|
| 92 |
-
|
| 93 |
-
suite.export(results, args.output)
|
| 94 |
-
|
| 95 |
-
# Print report
|
| 96 |
-
report = suite.report(results)
|
| 97 |
-
print(report)
|
| 98 |
-
|
| 99 |
-
print(f"\nResults saved to {args.output}")
|
| 100 |
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
| 101 |
|
| 102 |
-
|
| 103 |
-
|
| 104 |
-
data = json.load(f)
|
| 105 |
-
|
| 106 |
-
# Reconstruct BenchmarkResults for reporting
|
| 107 |
-
from aco.benchmarks.benchmark_suite import BenchmarkResult
|
| 108 |
-
results = {}
|
| 109 |
-
for name, d in data.items():
|
| 110 |
-
results[name] = BenchmarkResult(**d)
|
| 111 |
-
|
| 112 |
-
suite = BenchmarkSuite()
|
| 113 |
-
report = suite.report(results)
|
| 114 |
-
|
| 115 |
-
if args.output == "-":
|
| 116 |
-
print(report)
|
| 117 |
-
else:
|
| 118 |
-
with open(args.output, "w") as f:
|
| 119 |
-
f.write(report)
|
| 120 |
|
|
|
|
|
|
|
| 121 |
|
| 122 |
if __name__ == "__main__":
|
| 123 |
main()
|
|
|
|
| 1 |
+
"""ACO CLI: Command-line interface for the Agent Cost Optimizer."""
|
| 2 |
+
import argparse, json, sys
|
| 3 |
+
sys.path.insert(0, "/app")
|
| 4 |
+
from aco.optimizer import ACOOptimizer
|
|
|
|
|
|
|
|
|
|
|
|
|
| 5 |
from aco.config import ACOConfig
|
| 6 |
+
from aco.trace_schema import AgentTrace
|
|
|
|
| 7 |
|
| 8 |
def main():
|
| 9 |
+
parser = argparse.ArgumentParser(description="ACO: Agent Cost Optimizer")
|
| 10 |
+
sub = parser.add_subparsers(dest="command")
|
| 11 |
+
# Route
|
| 12 |
+
rp = sub.add_parser("route", help="Route a request to the optimal model")
|
| 13 |
+
rp.add_argument("request", help="The request text")
|
| 14 |
+
rp.add_argument("--task-type", default=None, help="Override task type")
|
| 15 |
+
rp.add_argument("--difficulty", type=int, default=None, help="Override difficulty")
|
| 16 |
+
# Budget
|
| 17 |
+
bp = sub.add_parser("budget", help="Compute context budget for a task")
|
| 18 |
+
bp.add_argument("request", help="The request text")
|
| 19 |
+
# Gate
|
| 20 |
+
gp = sub.add_parser("gate", help="Check if a tool call is worth it")
|
| 21 |
+
gp.add_argument("tool", help="Tool name")
|
| 22 |
+
gp.add_argument("--task-type", default="coding")
|
| 23 |
+
# Verify
|
| 24 |
+
vp = sub.add_parser("verify", help="Check if verification is needed")
|
| 25 |
+
vp.add_argument("--risk", default="medium", choices=["low","medium","high","critical"])
|
| 26 |
+
vp.add_argument("--confidence", type=float, default=0.8)
|
| 27 |
+
# Doom
|
| 28 |
+
dp = sub.add_parser("doom", help="Assess if a run is doomed")
|
| 29 |
+
dp.add_argument("--cost", type=float, default=0.0)
|
| 30 |
+
# Stats
|
| 31 |
+
sp = sub.add_parser("stats", help="Show optimizer statistics")
|
| 32 |
+
# Eval
|
| 33 |
+
ep = sub.add_parser("eval", help="Run benchmark evaluation")
|
| 34 |
+
ep.add_argument("--n", type=int, default=2000, help="Number of traces")
|
| 35 |
+
# Version
|
| 36 |
+
sub.add_parser("version", help="Show version")
|
| 37 |
+
|
| 38 |
args = parser.parse_args()
|
| 39 |
+
if args.command is None:
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
| 40 |
parser.print_help()
|
| 41 |
+
return
|
| 42 |
+
|
| 43 |
+
opt = ACOOptimizer()
|
| 44 |
|
| 45 |
+
if args.command == "route":
|
| 46 |
+
prediction = opt.classifier.classify(args.request)
|
| 47 |
+
tt = args.task_type or prediction["task_type"]
|
| 48 |
+
diff = args.difficulty or prediction["difficulty"]
|
| 49 |
+
routing = opt.router.route(args.request, tt, diff, prediction)
|
| 50 |
+
print(json.dumps({
|
| 51 |
+
"request": args.request[:80],
|
| 52 |
+
"task_type": tt,
|
| 53 |
+
"difficulty": diff,
|
| 54 |
+
"model_id": routing.model_id,
|
| 55 |
+
"tier": routing.tier,
|
| 56 |
+
"confidence": round(routing.confidence, 3),
|
| 57 |
+
"cost_estimate": routing.cost_estimate,
|
| 58 |
+
"escalated": routing.escalated,
|
| 59 |
+
"downgraded": routing.downgraded,
|
| 60 |
+
"reasoning": routing.reasoning,
|
| 61 |
+
}, indent=2))
|
| 62 |
|
| 63 |
+
elif args.command == "budget":
|
| 64 |
+
prediction = opt.classifier.classify(args.request)
|
| 65 |
+
budget = opt.context_budgeter.budget(
|
| 66 |
+
prediction["task_type"], prediction["difficulty"],
|
| 67 |
+
prediction["needs_retrieval"], prediction["needs_tools"])
|
| 68 |
+
print(json.dumps({
|
| 69 |
+
"total_tokens": budget.total_tokens,
|
| 70 |
+
"keep_exact": budget.keep_exact,
|
| 71 |
+
"summarize": budget.summarize,
|
| 72 |
+
"omit": budget.omit,
|
| 73 |
+
"retrieve_on_demand": budget.retrieve_on_demand,
|
| 74 |
+
"cache_prefix": budget.cache_prefix,
|
| 75 |
+
}, indent=2))
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
| 76 |
|
| 77 |
+
elif args.command == "gate":
|
| 78 |
+
decision = opt.tool_gate.gate(args.tool, {}, args.task_type, 1, 5, 0.5)
|
| 79 |
+
print(json.dumps({
|
| 80 |
+
"tool": args.tool,
|
| 81 |
+
"action": decision.action,
|
| 82 |
+
"confidence": decision.confidence,
|
| 83 |
+
"reasoning": decision.reasoning,
|
| 84 |
+
"estimated_cost": decision.estimated_cost,
|
| 85 |
+
}, indent=2))
|
| 86 |
|
| 87 |
+
elif args.command == "verify":
|
| 88 |
+
decision = opt.verifier_budgeter.should_verify(
|
| 89 |
+
"coding", args.risk, args.confidence)
|
| 90 |
+
print(json.dumps({
|
| 91 |
+
"should_verify": decision.should_verify,
|
| 92 |
+
"verifier_type": decision.verifier_type,
|
| 93 |
+
"reasoning": decision.reasoning,
|
| 94 |
+
"estimated_cost": decision.estimated_cost,
|
| 95 |
+
}, indent=2))
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
| 96 |
|
| 97 |
+
elif args.command == "doom":
|
| 98 |
+
assessment = opt.check_doom(args.cost)
|
| 99 |
+
print(json.dumps({
|
| 100 |
+
"doomed": assessment.doomed,
|
| 101 |
+
"severity": assessment.severity,
|
| 102 |
+
"action": assessment.recommended_action,
|
| 103 |
+
"reasoning": assessment.reasoning,
|
| 104 |
+
}, indent=2))
|
| 105 |
|
| 106 |
+
elif args.command == "stats":
|
| 107 |
+
print(json.dumps(opt.get_stats(), indent=2))
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
| 108 |
|
| 109 |
+
elif args.command == "version":
|
| 110 |
+
print("ACO v8.0 - Agent Cost Optimizer")
|
| 111 |
|
| 112 |
if __name__ == "__main__":
|
| 113 |
main()
|