christlurker's picture
FrontierAgent react demo
9d0fd45
Raw
History Blame Contribute Delete
3.23 kB
"""AssertionObserver — synthesize assertions from evidence on loop end.
Uses cluster-based grouping: evidence cards grouped by query,
each group becomes one assertion. No LLM call needed.
"""
from __future__ import annotations
from collections import defaultdict
from typing import Any
from frontier_agent.core.loop_types import AgentLoopResult, BaseObserver
class AssertionObserver(BaseObserver):
"""Synthesize assertions from evidence_cards at loop end.
critical=True because callers read metadata["assertions"] from the result.
"""
critical: bool = True
async def on_loop_end(self, result: AgentLoopResult) -> None:
evidence_cards: list[dict] = result.metadata.get("evidence_cards", [])
assertions = _cluster_assertions(evidence_cards)
# Fallback: single assertion from final_content if no evidence
if not assertions and result.final_content:
assertions = [{
"id": "as-react-001",
"statement": result.final_content[:500],
"confidence": 0.5,
"supporting_evidence": [],
"counter_evidence": [],
"is_disputed": False,
}]
result.metadata["assertions"] = assertions
def _default_confidence(avg_rel: float, count: int) -> float:
"""Confidence formula for research assertions."""
conf = avg_rel * 0.7 + min(count, 10) * 0.02
return round(max(0.1, min(0.80, conf)), 2)
def _benchmark_confidence(avg_rel: float, count: int) -> float:
"""Simpler confidence formula for benchmark solvers."""
return round(min(0.75, 0.4 + count * 0.05), 2)
def _cluster_assertions(
evidence_cards: list[dict],
confidence_fn: Any = None,
) -> list[dict]:
"""Group evidence by query -> one assertion per cluster."""
if not evidence_cards:
return []
if confidence_fn is None:
confidence_fn = _default_confidence
clusters: dict[str, list[dict]] = defaultdict(list)
for card in evidence_cards:
key = card.get("query", "").strip().lower()[:80] or "general"
clusters[key].append(card)
assertions: list[dict[str, Any]] = []
for i, (query, cards) in enumerate(clusters.items()):
claims = [
c.get("claim", "")[:100]
for c in cards[:3] if c.get("claim")
]
statement = (
f"{query}: " + "; ".join(claims) if claims else query
)
avg_rel = sum(
float(c.get("relevance_score", 0.3) or 0.3)
for c in cards
) / len(cards)
assertions.append({
"id": f"as-ev-{i + 1:03d}",
"statement": statement[:300],
"confidence": confidence_fn(avg_rel, len(cards)),
"supporting_evidence": [c["id"] for c in cards[:15]],
"counter_evidence": [],
"is_disputed": False,
})
return assertions
def extract_assertions_from_response(
response_text: str,
evidence_cards: list[dict],
) -> list[dict]:
"""Lightweight assertion placeholder for benchmark solvers."""
if not response_text or not evidence_cards:
return []
return _cluster_assertions(evidence_cards, _benchmark_confidence)