Spaces:
Paused
Paused
Download sensorflow/agentic/agents/base.py from whassan/SensorflowStudio: direct link, hf CLI and curl.
- Browser
- Download file 4.76 kB
-
https://huggingface.co/spaces/whassan/SensorflowStudio/resolve/main/sensorflow/agentic/agents/base.py
- Command line
-
hf download hf://spaces/whassan/SensorflowStudio/sensorflow/agentic/agents/base.py
-
curl -L -o base.py https://huggingface.co/spaces/whassan/SensorflowStudio/resolve/main/sensorflow/agentic/agents/base.py
4.76 kB
| """BaseAgent: the shared contract for every advisory agent. | |
| Design (mirrors sensorflow.evaluation.copilot): | |
| * `_analyze(...)` is the deterministic rule-based core — always runs, always | |
| testable offline. | |
| * `maybe_llm_rationale(...)` optionally asks a local Ollama endpoint for a | |
| natural-language rationale; any failure is swallowed and the deterministic | |
| output stands alone. The LLM can only ever ADD prose; it cannot change | |
| structured outputs, confidences, or verdicts. | |
| * Exceptions inside `_analyze` are converted to a failed AgentResult with | |
| escalation required — an agent crash can therefore never silently pass a | |
| stage (the pipeline treats it as missing evidence -> INDETERMINATE-ward). | |
| """ | |
| from __future__ import annotations | |
| import json | |
| from typing import Any, Dict, List, Optional, Tuple | |
| import httpx | |
| from sensorflow.agentic.models import AgentEscalation, AgentResult, now_iso | |
| # Local-only by default; kept short so offline runs fail fast. | |
| OLLAMA_ENDPOINTS = [ | |
| {"url": "http://localhost:11434/api/chat", "model": "gemma3:latest"}, | |
| ] | |
| LLM_TIMEOUT_S = 4.0 | |
| class BaseAgent: | |
| name: str = "base" | |
| version: str = "1.0.0" | |
| epistemic_status: str = "DERIVED" | |
| def __init__(self, use_llm: bool = False): | |
| self.use_llm = use_llm | |
| # -- to be provided by subclasses ----------------------------------- | |
| def _analyze(self, failure_id: str, **inputs) -> Tuple[Dict[str, Any], float, str, | |
| AgentEscalation]: | |
| """Return (output, confidence, confidence_basis, escalation).""" | |
| raise NotImplementedError | |
| def _llm_prompt(self, failure_id: str, output: Dict[str, Any], | |
| **inputs) -> Optional[str]: | |
| return None | |
| # -- uniform entry point --------------------------------------------- | |
| def run(self, failure_id: str, **inputs) -> AgentResult: | |
| started = now_iso() | |
| try: | |
| output, confidence, basis, escalation = self._analyze(failure_id, **inputs) | |
| status = "escalated" if escalation.required else "ok" | |
| result = AgentResult( | |
| agent=self.name, agent_version=self.version, | |
| failure_id=failure_id, status=status, output=output, | |
| confidence=confidence, confidence_basis=basis, | |
| epistemic_status=self.epistemic_status, | |
| escalation=escalation, started_at=started) | |
| except Exception as e: | |
| result = AgentResult( | |
| agent=self.name, agent_version=self.version, | |
| failure_id=failure_id, status="failed", | |
| output={"error": str(e)}, confidence=0.0, | |
| confidence_basis="agent raised an exception", | |
| escalation=AgentEscalation( | |
| required=True, | |
| reasons=[f"{self.name} failed: {e}"], | |
| human_review_triggers=["agent_failure"]), | |
| failure_handling=("exception captured; stage marked failed; " | |
| "downstream policy treats this as missing " | |
| "evidence (fail-safe)"), | |
| started_at=started) | |
| result.finished_at = now_iso() | |
| return result | |
| if self.use_llm: | |
| prompt = self._llm_prompt(failure_id, result.output, **inputs) | |
| if prompt: | |
| text, provider = _try_ollama(prompt) | |
| if text: | |
| result.llm_used = True | |
| result.llm_provider = provider | |
| result.llm_rationale = ( | |
| "LLM RATIONALE (advisory prose only; structured " | |
| "outputs above are deterministic): " + text) | |
| result.finished_at = now_iso() | |
| return result | |
| def _try_ollama(prompt: str) -> Tuple[Optional[str], Optional[str]]: | |
| for ep in OLLAMA_ENDPOINTS: | |
| try: | |
| res = httpx.post(ep["url"], json={ | |
| "model": ep["model"], | |
| "messages": [{"role": "user", "content": prompt}], | |
| "stream": False, | |
| }, timeout=LLM_TIMEOUT_S) | |
| if res.status_code == 200: | |
| text = res.json().get("message", {}).get("content", "") | |
| if text: | |
| return text, ep["url"] | |
| except Exception: | |
| continue | |
| return None, None | |
| def compact(obj: Any, limit: int = 3000) -> str: | |
| return json.dumps(obj, default=str)[:limit] | |
| def no_escalation() -> AgentEscalation: | |
| return AgentEscalation() | |
| def escalate(reasons: List[str], triggers: List[str]) -> AgentEscalation: | |
| return AgentEscalation(required=True, reasons=reasons, | |
| human_review_triggers=triggers) | |