Spaces:
Running
Running
| """ | |
| Spatial Atlas — Entropy-Guided Reasoning Engine | |
| Estimates information gain to optimize reasoning trajectories. | |
| Builds on the entropy-guided approach from Sprint 1. | |
| Core idea: Before each reasoning step, estimate which action | |
| would maximize information gain (reduce uncertainty the most). | |
| This leads to more efficient trajectories and better cost-efficiency scores. | |
| """ | |
| import json | |
| import logging | |
| from typing import Any | |
| logger = logging.getLogger("spatial-atlas.entropy") | |
| class EntropyEngine: | |
| """Estimate information gain to guide reasoning decisions.""" | |
| def __init__(self, llm): | |
| self.llm = llm | |
| async def select_best_action( | |
| self, | |
| knowledge_state: dict[str, Any], | |
| candidates: list[str], | |
| query: str, | |
| ) -> tuple[str, str]: | |
| """ | |
| Given current knowledge and candidate actions, pick the highest info-gain action. | |
| Returns: | |
| Tuple of (selected_action, reasoning) | |
| """ | |
| if len(candidates) <= 1: | |
| return candidates[0] if candidates else "", "Only one option available" | |
| state_summary = json.dumps(knowledge_state, indent=2, default=str) | |
| candidate_list = "\n".join(f"{i+1}. {c}" for i, c in enumerate(candidates)) | |
| prompt = f"""You are optimizing an information-gathering trajectory. | |
| Goal: Answer this question: {query} | |
| Current knowledge state: | |
| {state_summary} | |
| Candidate next actions: | |
| {candidate_list} | |
| For each action, estimate how much it would reduce uncertainty about answering the question. | |
| Rate each from 1-10 (10 = most informative, reduces uncertainty the most). | |
| Return JSON: | |
| {{"rankings": [{{"action_index": 0, "info_gain": 8, "reason": "..."}}]}}""" | |
| try: | |
| result = await self.llm.generate(prompt, model_tier="fast", json_mode=True) | |
| parsed = json.loads(result) | |
| rankings = parsed.get("rankings", []) | |
| if rankings: | |
| best = max(rankings, key=lambda r: r.get("info_gain", 0)) | |
| idx = best.get("action_index", 0) | |
| reason = best.get("reason", "Highest estimated information gain") | |
| if 0 <= idx < len(candidates): | |
| logger.info(f"Entropy: selected action {idx} (gain={best.get('info_gain')})") | |
| return candidates[idx], reason | |
| except Exception as e: | |
| logger.warning(f"Entropy engine fallback (error: {e})") | |
| # Fallback: first candidate | |
| return candidates[0], "Fallback selection" | |
| async def estimate_confidence( | |
| self, | |
| answer: str, | |
| evidence: str, | |
| query: str, | |
| ) -> float: | |
| """ | |
| Estimate confidence in an answer given the evidence. | |
| Returns 0.0-1.0 confidence score. | |
| Used to decide whether to reflect/refine. | |
| """ | |
| prompt = f"""Rate your confidence that this answer correctly addresses the question. | |
| Question: {query} | |
| Evidence summary (truncated): | |
| {evidence[:2000]} | |
| Proposed answer: | |
| {answer} | |
| Rate confidence from 0.0 (no confidence) to 1.0 (fully confident). | |
| Consider: Does the evidence support the answer? Are there gaps? | |
| Return JSON: {{"confidence": 0.85, "gaps": ["list of any gaps"]}}""" | |
| try: | |
| result = await self.llm.generate(prompt, model_tier="fast", json_mode=True) | |
| parsed = json.loads(result) | |
| return float(parsed.get("confidence", 0.5)) | |
| except Exception: | |
| return 0.5 # Default moderate confidence | |