@@ -332,21 +332,21 @@ def build_optimization_prompt(context: AiOptimizationContext) -> str:
332332def call_ai_optimization_decision (
333333 context : AiOptimizationContext ,
334334 * ,
335- provider : str = "anthropic" ,
336335 dry_run : bool = False ,
337336) -> dict [str , Any ]:
338- """Call an AI model (via ai_audit.py) to decide on optimization.
337+ """Call AiGateway to decide whether optimization is needed.
338+
339+ Routes through AiGateway (Claude/GPT via LlmAdapter).
340+ No API keys needed — CODEX_AUDIT_SERVICE_URL only.
339341
340342 Args:
341343 context: The optimization context with drift and snapshot data.
342- provider: "anthropic", "openai", or "codex".
343- dry_run: If True, return a simulated decision.
344+ dry_run: If True, return a simulated decision without AI call.
344345
345346 Returns:
346347 AI decision dict with optimization_needed, reason, etc.
347348 """
348349 if dry_run :
349- # Simulate a decision based on drift status
350350 if context .drift and context .drift .status in (DriftStatus .REVIEW , DriftStatus .CRITICAL ):
351351 return {
352352 "optimization_needed" : True ,
@@ -364,33 +364,32 @@ def call_ai_optimization_decision(
364364 "confidence" : 0.95 ,
365365 }
366366
367- # Try using ai_audit.py from QuantStrategyPlugins
368367 try :
369- from quant_strategy_plugins .ai_audit import AiAuditEndpoint , call_ai_audit
370-
371- endpoint = AiAuditEndpoint (
372- name = "strategy_optimizer" ,
373- api_key = os .environ .get ("AI_AUDIT_API_KEY" , os .environ .get ("ANTHROPIC_API_KEY" , "" )),
374- provider = provider ,
375- model = "claude-sonnet-4-6" if provider == "anthropic" else "gpt-5.4-mini" ,
368+ from quant_platform_kit .strategy_lifecycle .ai_provider import (
369+ AiServiceConfig , AiServiceClient , AiProviderConfig ,
376370 )
377371
372+ config = AiServiceConfig .from_env ()
373+ if not config .reviewers :
374+ return {"optimization_needed" : False , "reason" : "No AI backend configured (set CODEX_AUDIT_SERVICE_URL)" }
375+
376+ client = AiServiceClient (config )
378377 prompt = build_optimization_prompt (context )
379- messages = [{"role" : "user" , "content" : prompt }]
380-
381- raw = call_ai_audit (endpoint , messages , timeout = 30.0 )
382- if isinstance (raw , str ):
383- # Try to extract JSON from the response
384- import re
385- match = re .search (r"\{[\s\S]*\}" , raw )
386- if match :
387- return json .loads (match .group (0 ))
388- return {"optimization_needed" : False , "reason" : "Could not parse AI response" , "raw" : raw [:500 ]}
389- return raw if isinstance (raw , Mapping ) else {"optimization_needed" : False , "reason" : "Unexpected response type" }
378+ results = client .review (prompt , timeout = 30.0 )
379+
380+ # Use the first successful reviewer result
381+ for r in results :
382+ if r .success and r .output :
383+ import re
384+ match = re .search (r"\{[\s\S]*\}" , r .output )
385+ if match :
386+ return json .loads (match .group (0 ))
387+ return {"optimization_needed" : False , "reason" : "Could not parse AI response" , "raw" : r .output [:500 ]}
388+
389+ return {"optimization_needed" : False , "reason" : "All AI backends unavailable" }
390390
391391 except ImportError :
392- # Fallback: use the dry_run heuristic
393- return call_ai_optimization_decision (context , provider = provider , dry_run = True )
392+ return call_ai_optimization_decision (context , dry_run = True )
394393 except Exception as exc :
395394 return {"optimization_needed" : False , "reason" : f"AI call failed: { exc } " , "error" : str (exc )}
396395
0 commit comments