Spaces:
Running
Running
File size: 1,537 Bytes
68025ee | 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 | import json
import re
import logging
from llm.openrouter import OpenRouterClient
logger = logging.getLogger(__name__)
FALLBACK_DECISION = {"action": "HOLD", "size": 0.0, "confidence": 0.0, "reason": "Parse error — defaulting to HOLD"}
class Agent:
def __init__(self, role: str, system_prompt: str, llm_client: OpenRouterClient):
self.role = role
self.system_prompt = system_prompt
self.llm = llm_client
def run(self, context: dict) -> dict:
prompt = self.build_prompt(context)
raw = self.llm.call(self.system_prompt, prompt)
return self.parse(raw)
def build_prompt(self, context: dict) -> str:
raise NotImplementedError
def parse(self, raw: str) -> dict:
"""Robust JSON parsing: strip markdown fences, regex fallback."""
if not raw:
return FALLBACK_DECISION.copy()
# Strip markdown code fences
cleaned = re.sub(r"```(?:json)?\s*", "", raw).strip()
cleaned = re.sub(r"```\s*$", "", cleaned).strip()
# Try direct parse
try:
return json.loads(cleaned)
except json.JSONDecodeError:
pass
# Try to extract first JSON object
match = re.search(r"\{[^{}]*\}", cleaned, re.DOTALL)
if match:
try:
return json.loads(match.group())
except json.JSONDecodeError:
pass
logger.warning(f"[{self.role}] Failed to parse response: {raw[:200]}")
return FALLBACK_DECISION.copy()
|