Spaces:
Running
Running
File size: 13,378 Bytes
039dd77 8fc7ac7 039dd77 4867bc1 039dd77 8fc7ac7 039dd77 4867bc1 039dd77 4867bc1 8fc7ac7 039dd77 8fc7ac7 039dd77 4867bc1 039dd77 4867bc1 039dd77 4867bc1 039dd77 8fc7ac7 039dd77 4867bc1 039dd77 4867bc1 8fc7ac7 039dd77 4867bc1 8fc7ac7 4867bc1 039dd77 4867bc1 039dd77 4867bc1 039dd77 4867bc1 8fc7ac7 039dd77 8fc7ac7 039dd77 4867bc1 039dd77 8fc7ac7 039dd77 | 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 51 52 53 54 55 56 57 58 59 60 61 62 63 64 65 66 67 68 69 70 71 72 73 74 75 76 77 78 79 80 81 82 83 84 85 86 87 88 89 90 91 92 93 94 95 96 97 98 99 100 101 102 103 104 105 106 107 108 109 110 111 112 113 114 115 116 117 118 119 120 121 122 123 124 125 126 127 128 129 130 131 132 133 134 135 136 137 138 139 140 141 142 143 144 145 146 147 148 149 150 151 152 153 154 155 156 157 158 159 160 161 162 163 164 165 166 167 168 169 170 171 172 173 174 175 176 177 178 179 180 181 182 183 184 185 186 187 188 189 190 191 192 193 194 195 196 197 198 199 200 201 202 203 204 205 206 207 208 209 210 211 212 213 214 215 216 217 218 219 220 221 222 223 224 225 226 227 228 229 230 231 232 233 234 235 236 237 238 239 240 241 242 243 244 245 246 247 248 249 250 251 252 253 254 255 256 257 258 259 260 261 262 263 264 265 266 267 268 269 270 271 272 273 274 275 276 277 278 279 280 281 282 283 284 285 286 287 288 289 290 291 292 293 294 295 296 297 298 299 300 301 302 303 304 305 306 307 308 309 310 311 | """ayllu.backend — the LIVE model backend for ayllu, via a11oy's OWN orchestrator.
Honest wiring: ayllu never talks to a provider directly. It delegates to
`a11oy_code_orchestrator.agent_model_complete`, which owns model routing (route()),
resilient fallback, and per-completion energy receipts, and which returns a
CLEARLY-LABELED deterministic stub (never a fabricated answer) when neither a
reachable local endpoint nor a credentialed remote provider is available. The
live/stub decision is a11oy's, resolved at RUNTIME with no redeploy.
Each turn is wrapped in an a11oy OTel span (szl_observability.span) when present.
Everything here is guarded: if a11oy's modules are absent, model_complete returns an
honest stub dict — it NEVER fabricates an answer and NEVER claims a wiring it lacks.
"""
from __future__ import annotations
import asyncio
import contextlib
import hashlib
import json
from typing import Any, Optional
def _span(name: str, **attrs: Any):
"""a11oy OTel span if present, else a silent no-op context manager (honest)."""
try:
import szl_observability as _obs # type: ignore
return _obs.span(name, **attrs)
except Exception:
return contextlib.nullcontext()
def backend_status() -> dict[str, Any]:
"""Side-effect-free, honest snapshot of what the model backend can do NOW."""
orch = None
orch_err: Optional[str] = None
try:
import a11oy_code_orchestrator as _o # type: ignore
orch = _o
except Exception as exc:
orch_err = str(exc)[:160]
has_cred = False
local_ready = False
backend_ready = False
cred_checked = False
if orch is not None:
try:
has_cred = bool(orch._resolve_hf_token()) or any(
orch._resolve_provider_keys().values())
_base, local_ready = orch._serving_base()
readiness = getattr(orch, "inference_backend_ready", None)
backend_ready = bool(readiness() if callable(readiness)
else orch.has_inference_credential() or local_ready)
cred_checked = True
except Exception:
cred_checked = False
profile_runtime = None
if orch is not None:
try:
profile_status = getattr(orch, "forge_profile_runtime_status", None)
profile_runtime = profile_status() if callable(profile_status) else None
except Exception:
profile_runtime = None
if orch is None:
mode = "unavailable"
elif not cred_checked:
mode = "unknown"
elif backend_ready:
mode = "live"
else:
mode = "stub"
return {
"orchestrator_available": orch is not None,
"orchestrator_error": orch_err,
"credential_checked": cred_checked,
"has_credential": has_cred,
"local_backend_ready": local_ready,
"backend_ready": backend_ready,
"mode": mode,
"note": {
"unavailable": "a11oy_code_orchestrator not importable — ask/council return "
"an honest stub.",
"unknown": "orchestrator present but credential state could not be read.",
"live": ("real model answers via a11oy routing + receipts; source is a "
"reachable local backend or a credentialed remote provider. "
"Outputs remain unverified model text."),
"stub": ("no reachable local backend or remote inference credential — "
"clearly-labeled deterministic stub, no fabrication."),
}.get(mode, ""),
"backend": "a11oy_code_orchestrator.agent_model_complete",
"forge_profiles": profile_runtime,
}
async def model_complete(
system: str,
prompt: str,
tier: Optional[str] = None,
*,
persona: Optional[str] = None,
max_tokens: int = 1000,
temperature: float = 0.4,
timeout_s: float = 45.0,
**_ignored: Any,
) -> dict[str, Any]:
"""Adapter matching ayllu.loop.run_turn's model_complete contract.
Returns {text, model, stub[, energy_receipt]}. Delegates to a11oy's orchestrator;
on ANY failure returns an honest stub (stub=True) — never a fabricated answer. The
`tier` argument is advisory only: the orchestrator selects the actual model itself.
"""
messages = [
{"role": "system", "content": system or ""},
{"role": "user", "content": prompt or ""},
]
with _span("ayllu.turn", persona=persona or "", tier_advisory=tier or ""):
try:
import a11oy_code_orchestrator as _o # type: ignore
except Exception as exc:
return {
"text": f"[honest: a11oy_code_orchestrator unavailable "
f"({str(exc)[:120]}); no model backend, no fabricated answer]",
"model": "unavailable",
"stub": True,
}
bounded_tokens = max(1, min(int(max_tokens), 2048))
bounded_timeout = max(0.1, min(float(timeout_s), 120.0))
profile = None
try:
from .model_binding import persona_binding
profile = persona_binding(persona or "")["primary_profile"]
except Exception:
profile = None
grounding = None
if profile == "BrainNavigator-v1":
try:
grounding = await asyncio.to_thread(
_o.agent_rag_context, prompt or "", k=6)
except Exception as exc:
grounding = {
"schema": "szl.brain.navigator-context/v1",
"state": "ABSTAIN_RETRIEVAL_ERROR",
"ready": False,
"content_access": "HANDLES_ONLY",
"handles": [],
"evidence": [],
"honesty": f"Brain retrieval raised {type(exc).__name__}; no grounding fabricated",
}
if not grounding.get("ready"):
attestation = None
try:
attestation = await asyncio.to_thread(
_o.attest_local_model, profile)
except Exception:
pass
return {
"text": None,
"model": ((attestation or {}).get("expected_model") or "khipu-unavailable"),
"stub": True,
"timeout": False,
"token_budget": bounded_tokens,
"timeout_s": bounded_timeout,
"honesty": (grounding.get("honesty") or
"no Brain evidence cleared the retrieval gate; abstaining"),
"grounding": grounding,
"model_attestation": attestation,
}
messages[1]["content"] = (
(prompt or "")
+ "\n\nCANDIDATE_HANDLES_JSON (controller-provided; no node content):\n"
+ json.dumps(grounding["handles"], sort_keys=True,
separators=(",", ":"), ensure_ascii=False)
+ "\nReturn a retrieval plan using only offered nodeId values. "
"If none supports the query, return ABSTAIN with zero citations."
)
grounding["augmented_prompt_sha256"] = hashlib.sha256(
messages[1]["content"].encode("utf-8")).hexdigest()
try:
result = await asyncio.wait_for(
_o.agent_model_complete(
messages, max_tokens=bounded_tokens, temperature=temperature,
local_profile=profile),
timeout=bounded_timeout,
)
except asyncio.TimeoutError:
return {
"text": None,
"model": "timeout",
"stub": True,
"timeout": True,
"token_budget": bounded_tokens,
"timeout_s": bounded_timeout,
"honesty": (
f"model turn exceeded the {bounded_timeout:g}s deadline; "
"the request was cancelled and no answer was fabricated"
),
}
except Exception as exc:
return {
"text": None,
"model": "error",
"stub": True,
"timeout": False,
"token_budget": bounded_tokens,
"timeout_s": bounded_timeout,
"honesty": (
f"agent_model_complete raised: {str(exc)[:160]}; "
"no answer was fabricated"
),
}
if not isinstance(result, dict):
return {
"text": None,
"model": "unknown",
"stub": True,
"timeout": False,
"token_budget": bounded_tokens,
"timeout_s": bounded_timeout,
"honesty": "model backend returned a non-contract value; no answer was used",
}
answer = result.get("text", "")
if profile == "BrainNavigator-v1" and grounding is not None:
citation_state = "NOT_DECLARED_UNSTRUCTURED_OUTPUT"
cited_node_ids: list[str] = []
citation_error = None
if isinstance(answer, str):
candidate = answer.strip()
if candidate.startswith("```") and candidate.endswith("```"):
candidate = candidate[3:-3].strip()
if candidate.lower().startswith("json"):
candidate = candidate[4:].lstrip()
try:
parsed_answer = json.loads(candidate)
except (TypeError, ValueError):
parsed_answer = None
if isinstance(parsed_answer, dict):
declared = (
parsed_answer.get("citedNodeIds")
if "citedNodeIds" in parsed_answer
else parsed_answer.get("cited_node_ids")
if "cited_node_ids" in parsed_answer
else None
)
if declared is not None:
if (not isinstance(declared, list)
or any(not isinstance(item, str) or not item
for item in declared)):
citation_state = "INVALID_CITATION_CONTRACT"
citation_error = "cited node IDs must be a list of non-empty strings"
else:
cited_node_ids = list(dict.fromkeys(declared))
offered = {
row.get("nodeId") for row in grounding.get("handles", [])
if isinstance(row, dict) and isinstance(row.get("nodeId"), str)
}
unknown = sorted(set(cited_node_ids) - offered)
if unknown:
citation_state = "UNKNOWN_CITATION_REFUSED"
citation_error = (
"model cited node IDs outside the controller-offered handle set"
)
else:
citation_state = "CITATIONS_WITHIN_OFFERED_HANDLES"
grounding["citation_validation"] = {
"state": citation_state,
"cited_node_ids": cited_node_ids,
"cited_node_ids_sha256": hashlib.sha256(json.dumps(
cited_node_ids, sort_keys=True, separators=(",", ":"),
ensure_ascii=False
).encode("utf-8")).hexdigest(),
}
if citation_error:
grounding["citation_validation"]["honesty"] = citation_error
rejected_output_sha256 = (
hashlib.sha256(answer.encode("utf-8")).hexdigest()
if isinstance(answer, str) else None
)
grounding["rejected_model_output_sha256"] = rejected_output_sha256
return {
"text": None,
"model": result.get("model"),
"stub": True,
"timeout": bool(result.get("timeout", False)),
"token_budget": bounded_tokens,
"timeout_s": bounded_timeout,
"honesty": citation_error + "; no ungrounded model text returned",
"raw_model_output_sha256": rejected_output_sha256,
"energy_receipt": result.get("energy_receipt"),
"model_attestation": result.get("model_attestation"),
"grounding": grounding,
}
return {
"text": answer,
"model": result.get("model"),
"stub": bool(result.get("stub")),
"timeout": bool(result.get("timeout", False)),
"token_budget": bounded_tokens,
"timeout_s": bounded_timeout,
"honesty": result.get("honesty"),
"energy_receipt": result.get("energy_receipt"),
"model_attestation": result.get("model_attestation"),
"grounding": grounding,
}
|