cgae_arc_backend / agents /runner.py
rb512's picture
Upload agents/runner.py with huggingface_hub
459decf verified
Raw
History Blame Contribute Delete
7.39 kB
"""
Portfolio Runner β€” Orchestrates the CGAE Adaptive Portfolio Manager demo.
Flow:
1. Create sub-agents (RegimeDetector, Rebalancer, YieldOptimizer)
2. Run portfolio management cycles
3. Adversarial agent attacks each cycle β€” all blocked by CGAE
4. Display results
"""
from __future__ import annotations
import json
import logging
import time
import urllib.request
from typing import Optional
from dotenv import load_dotenv
load_dotenv()
from cgae_engine.gate import GateFunction, RobustnessVector, Tier
from cgae_engine.llm_agent import create_llm_agents
from cgae_engine.models_config import CONTESTANT_MODELS
from cgae_engine.audit import AuditOrchestrator
from agents.portfolio import (
PortfolioOrchestrator, RegimeDetector, Rebalancer,
YieldOptimizer, SubAgent, Allocation, Regime,
)
from agents.adversarial import AdversarialAgent
logger = logging.getLogger(__name__)
def fetch_market_data() -> dict:
"""Fetch live market data for regime detection."""
try:
url = "https://api.coingecko.com/api/v3/simple/price?ids=ethereum,bitcoin&vs_currencies=usd&include_24hr_change=true"
req = urllib.request.Request(url, headers={"Accept": "application/json"})
with urllib.request.urlopen(req, timeout=10) as resp:
data = json.loads(resp.read())
return {
"eth_change_24h": data["ethereum"].get("usd_24h_change", 0),
"btc_change_24h": data["bitcoin"].get("usd_24h_change", 0),
"volatility": abs(data["ethereum"].get("usd_24h_change", 0)) * 0.5,
"funding_rate": 0.01,
"fear_greed": 55,
}
except Exception as e:
logger.warning(f"Market data fetch failed: {e}")
return {"eth_change_24h": 1.5, "btc_change_24h": 0.8, "volatility": 3.0, "funding_rate": 0.01, "fear_greed": 55}
def create_portfolio_system() -> tuple[PortfolioOrchestrator, AdversarialAgent]:
"""Create the full portfolio system with all sub-agents."""
gate = GateFunction()
models = {m["model_name"]: m for m in CONTESTANT_MODELS}
llm_agents = create_llm_agents(list(models.values()))
# Fetch real robustness scores from framework APIs where available
orchestrator_audit = AuditOrchestrator()
agent_scores = {}
for name in ["nova-pro", "DeepSeek-V3.2", "Kimi-K2.5", "MiniMax-M2.5"]:
result = orchestrator_audit.audit_from_results(name, name)
agent_scores[name] = result.robustness
defaults = result.defaults_used
tier = gate.evaluate(result.robustness)
logger.info(f" {name}: CC={result.robustness.cc:.3f} ER={result.robustness.er:.3f} "
f"AS={result.robustness.as_:.3f} IH={result.robustness.ih:.3f} β†’ T{tier.value}"
f"{' (defaults: ' + ','.join(defaults) + ')' if defaults else ''}")
regime_r = agent_scores["nova-pro"]
rebal_r = agent_scores["Kimi-K2.5"]
yield_r = agent_scores["DeepSeek-V3.2"]
regime_detector = RegimeDetector(
name="nova-pro", role="regime_detector",
llm=llm_agents["nova-pro"],
tier=gate.evaluate(regime_r),
robustness=regime_r,
) if "nova-pro" in llm_agents else None
rebalancer = Rebalancer(
name="Kimi-K2.5", role="rebalancer",
llm=llm_agents["Kimi-K2.5"],
tier=gate.evaluate(rebal_r),
robustness=rebal_r,
) if "Kimi-K2.5" in llm_agents else None
yield_optimizer = YieldOptimizer(
name="DeepSeek-V3.2", role="yield_optimizer",
llm=llm_agents["DeepSeek-V3.2"],
tier=gate.evaluate(yield_r),
robustness=yield_r,
) if "DeepSeek-V3.2" in llm_agents else None
if not all([regime_detector, rebalancer, yield_optimizer]):
raise RuntimeError("Could not create all sub-agents. Check AWS credentials.")
orchestrator = PortfolioOrchestrator(
regime_detector=regime_detector,
rebalancer=rebalancer,
yield_optimizer=yield_optimizer,
tier=Tier.T4, # Orchestrator has highest tier
)
# MiniMax-M2.5 as adversary β€” uses its real (low) robustness scores
minimax_r = agent_scores["MiniMax-M2.5"]
minimax_tier = gate.evaluate(minimax_r)
adversary = AdversarialAgent(tier=minimax_tier, robustness=minimax_r)
return orchestrator, adversary
def run_demo(rounds: int = 2, interval: int = 5):
"""Run the full portfolio management demo with adversary attacks."""
logging.basicConfig(level=logging.INFO, format="%(message)s")
print("=" * 65)
print(" CGAE Adaptive Portfolio Manager β€” Arc Γ— Circle (RFB 04)")
print("=" * 65)
orchestrator, adversary = create_portfolio_system()
# Print agent roster
print(f"\n{'─' * 65}")
print(" AGENT ROSTER")
print(f"{'─' * 65}")
agents = [
("Orchestrator", "coordinator", Tier.T4),
(orchestrator.regime_detector.name, "regime_detector", orchestrator.regime_detector.tier),
(orchestrator.rebalancer.name, "rebalancer", orchestrator.rebalancer.tier),
(orchestrator.yield_optimizer.name, "yield_optimizer", orchestrator.yield_optimizer.tier),
("adversary", "adversarial", adversary.tier),
]
print(f" {'Agent':<20} {'Role':<18} {'Tier':<5} {'Budget':<10}")
print(f" {'-'*53}")
for name, role, tier in agents:
budget = f"${GateFunction().budget_ceiling(tier)}"
print(f" {name:<20} {role:<18} T{tier.value:<4} {budget}")
# Run cycles
for i in range(rounds):
print(f"\n{'═' * 65}")
print(f" CYCLE {i+1}/{rounds}")
print(f"{'═' * 65}")
# Portfolio management
print(f"\n πŸ“ˆ Portfolio Management")
print(f" {'─' * 40}")
market = fetch_market_data()
result = orchestrator.run_cycle(market)
# Adversary attacks
print(f"\n πŸ”΄ Adversary Attacks")
print(f" {'─' * 40}")
attacks = adversary.run_all_attacks()
for attack in attacks:
status = "β›” BLOCKED" if attack.blocked else "⚠️ PASSED"
print(f" {status}: {attack.attack_type.value}")
print(f" └─ {attack.description}")
if i < rounds - 1:
time.sleep(interval)
# Final summary
print(f"\n{'═' * 65}")
print(" FINAL STATE")
print(f"{'═' * 65}")
ps = orchestrator.summary()
print(f"\n Portfolio: ${ps['aum']:.2f} AUM | Regime: {ps['regime']}")
print(f" Allocation: ETH={ps['allocation']['eth']:.0f}% BTC={ps['allocation']['btc']:.0f}% "
f"USDC={ps['allocation']['usdc']:.0f}% USYC={ps['allocation']['usyc']:.0f}%")
print(f" Delegations: {ps['total_delegations']} | Blocks: {ps['total_blocks']}")
pay = ps.get("payments", {})
if pay:
print(f"\n πŸ’Έ Nanopayments (x402 via Gateway):")
print(f" Spent: ${pay.get('spent', 0):.4f} / ${pay.get('budget_ceiling', 0)} ceiling")
print(f" Payments: {pay.get('payments_made', 0)} made, {pay.get('payments_blocked', 0)} blocked")
adv = adversary.summary()
print(f"\n Adversary: {adv['blocked']}/{adv['total_attacks']} attacks blocked "
f"({(1-adv['success_rate'])*100:.0f}% defense rate)")
print(f" Theorems enforced: {', '.join(set(a['theorem'][:20]+'...' for a in adv['attacks']))}")
return {"portfolio": ps, "adversary": adv}
if __name__ == "__main__":
run_demo()