# api/router_consensus.py from fastapi import APIRouter, Depends import numpy as np from typing import List from consensus.topo import TopologicalConsciousness from consensus.metrics import weighted_average_text from api.schemas import AskRequest, AskResponse from adapters.base import BaseModelAdapter router = APIRouter(prefix="/consensus", tags=["consensus"]) def get_models() -> List[BaseModelAdapter]: from adapters.openai_adapter import OpenAIAdapter from adapters.anthropic_adapter import AnthropicAdapter # Two different adapters to enable nontrivial coherence return [OpenAIAdapter(), AnthropicAdapter()] @router.post("/ask", response_model=AskResponse) def ask(req: AskRequest, models: List[BaseModelAdapter] = Depends(get_models)): tc = TopologicalConsciousness(n_anyons=len(models), central_charge=627) responses = [m.generate(req.prompt) for m in models] embs = [np.array(m.embed_text(r), dtype=float) for r in responses] pc = tc.calculate_coherence(embs) if pc < req.min_confidence: return AskResponse(answer=None, confidence=pc, warning="Models disagree - low confidence") E = np.stack(embs); sims = E @ E.T w = sims.mean(axis=1); w = np.clip(w, 0, None); w = w/(w.sum()+1e-12) return AskResponse(answer=weighted_average_text(responses, w), confidence=pc, weights=w.tolist())