bioma-framework 1.0.0__py3-none-any.whl
This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
- bioma/__init__.py +26 -0
- bioma/esg.py +99 -0
- bioma/esg_report.py +123 -0
- bioma/firewall_client.py +223 -0
- bioma/gateway.py +431 -0
- bioma/openrouter_client.py +159 -0
- bioma/server.py +137 -0
- bioma/vision.py +280 -0
- bioma_framework-1.0.0.dist-info/METADATA +232 -0
- bioma_framework-1.0.0.dist-info/RECORD +13 -0
- bioma_framework-1.0.0.dist-info/WHEEL +4 -0
- bioma_framework-1.0.0.dist-info/entry_points.txt +2 -0
- bioma_framework-1.0.0.dist-info/licenses/LICENSE +114 -0
bioma/__init__.py
ADDED
|
@@ -0,0 +1,26 @@
|
|
|
1
|
+
"""
|
|
2
|
+
B.I.O.M.A. — a lean efficiency & resilience micro-kernel for LLM infrastructure.
|
|
3
|
+
|
|
4
|
+
Two proven primitives, exposed from the Rust kernel (`bioma_micro`) plus a
|
|
5
|
+
resilient OpenRouter abstraction and a drop-in gateway:
|
|
6
|
+
|
|
7
|
+
* `kernel.HormonalBus` — lock-free in-memory signal injection (~2M sig/s, ~5μs)
|
|
8
|
+
* `kernel.dehydrate` / `kernel.ContextApoptosis` — autonomous context apoptosis
|
|
9
|
+
* `LeanOpenRouterClient` — resilient async dispatch with kernel-side apoptosis
|
|
10
|
+
* `bioma.gateway` — OpenAI/Anthropic drop-in gateway (`pip install bioma[gateway]`)
|
|
11
|
+
|
|
12
|
+
The optional integrations (`LeanOpenRouterClient` needs `openai`) are imported
|
|
13
|
+
lazily, so `import bioma` stays light for kernel-only use.
|
|
14
|
+
"""
|
|
15
|
+
import bioma_micro as kernel # the compiled Rust micro-kernel
|
|
16
|
+
|
|
17
|
+
__all__ = ["kernel", "LeanOpenRouterClient", "Dispatch"]
|
|
18
|
+
__version__ = "1.0.0"
|
|
19
|
+
|
|
20
|
+
|
|
21
|
+
def __getattr__(name: str):
|
|
22
|
+
# PEP 562 lazy import — pull the openai-backed client only when actually used
|
|
23
|
+
if name in ("LeanOpenRouterClient", "Dispatch"):
|
|
24
|
+
from bioma.openrouter_client import Dispatch, LeanOpenRouterClient
|
|
25
|
+
return {"LeanOpenRouterClient": LeanOpenRouterClient, "Dispatch": Dispatch}[name]
|
|
26
|
+
raise AttributeError(f"module {__name__!r} has no attribute {name!r}")
|
bioma/esg.py
ADDED
|
@@ -0,0 +1,99 @@
|
|
|
1
|
+
"""
|
|
2
|
+
`bioma/esg.py` — the official Frugal-AI KPI of the project: **energy per token**.
|
|
3
|
+
|
|
4
|
+
Converts MEASURED token savings (the kernel's per-dispatch audit) into energy
|
|
5
|
+
(Wh) and emissions (gCO2e) estimates using DECLARED literature coefficients.
|
|
6
|
+
The tokens are ground truth; the conversion is an estimate — every function
|
|
7
|
+
returns (low, mid, high) bounds and never a single unqualified number.
|
|
8
|
+
|
|
9
|
+
Coefficients (declared, replace with your own measurements when available):
|
|
10
|
+
|
|
11
|
+
* Datacenter LLM inference energy: **0.5–1.3 kWh per million tokens**
|
|
12
|
+
(mid 0.9). Range adopted from the public literature — consistent with
|
|
13
|
+
Epoch AI's ~0.3 Wh per GPT-4o query (~500-token answer) and 2024–2025
|
|
14
|
+
meta-analyses of production frontier-model inference. Our own CPU-laptop
|
|
15
|
+
measurement (reports/BIOMA_ENERGY_LOCAL.md: 0.754 Wh / 7,481 tok ≈
|
|
16
|
+
0.10 kWh/M tok, MARGINAL — idle and PUE excluded, 1B-parameter model,
|
|
17
|
+
prefill-heavy) sits below that range, as expected for a tiny model
|
|
18
|
+
measured marginally; the literature range targets production-scale
|
|
19
|
+
frontier inference. The KPI's reduction % is coefficient-independent.
|
|
20
|
+
* Grid carbon intensity presets (gCO2e/kWh): world ≈ 445 (IEA 2024),
|
|
21
|
+
EU ≈ 230 (EEA), US ≈ 385 (EPA eGRID), BR ≈ 100 (hydro-heavy, EPE/ONS).
|
|
22
|
+
* Prompt-caching adjustment: cached prefill tokens are not free — they are
|
|
23
|
+
billed/computed at a fraction of full price. `cache_adjust` shrinks the
|
|
24
|
+
claimed saving accordingly: saving × ((1−hit) + hit·cache_cost).
|
|
25
|
+
|
|
26
|
+
Usage:
|
|
27
|
+
from bioma.esg import estimate_saving, DEFAULTS
|
|
28
|
+
est = estimate_saving(tokens_saved=45_868) # one 16-round session
|
|
29
|
+
est["wh"] # (low, mid, high) Wh saved
|
|
30
|
+
est["gco2e"] # (low, mid, high) gCO2e saved, world grid
|
|
31
|
+
"""
|
|
32
|
+
from __future__ import annotations
|
|
33
|
+
|
|
34
|
+
from typing import TypedDict
|
|
35
|
+
|
|
36
|
+
# kWh per MILLION tokens — declared literature range (see module docstring).
|
|
37
|
+
KWH_PER_MTOK = {"low": 0.5, "mid": 0.9, "high": 1.3}
|
|
38
|
+
|
|
39
|
+
# gCO2e per kWh — grid presets (replace with your grid's factor).
|
|
40
|
+
GRID_GCO2_PER_KWH = {"world": 445.0, "eu": 230.0, "us": 385.0, "br": 100.0}
|
|
41
|
+
|
|
42
|
+
DEFAULTS = {"grid": "world", "cache_hit": 0.0, "cache_cost": 0.10}
|
|
43
|
+
|
|
44
|
+
|
|
45
|
+
class Estimate(TypedDict):
|
|
46
|
+
tokens_saved: int
|
|
47
|
+
cache_multiplier: float
|
|
48
|
+
wh: tuple[float, float, float]
|
|
49
|
+
gco2e: tuple[float, float, float]
|
|
50
|
+
grid: str
|
|
51
|
+
kwh_per_mtok: dict
|
|
52
|
+
|
|
53
|
+
|
|
54
|
+
def cache_multiplier(cache_hit: float, cache_cost: float = 0.10) -> float:
|
|
55
|
+
"""Fraction of the nominal saving that survives an honest caching baseline.
|
|
56
|
+
|
|
57
|
+
If `cache_hit` of the resent context would have been a cache hit anyway
|
|
58
|
+
(costing `cache_cost` of a full prefill), the counterfactual baseline is
|
|
59
|
+
cheaper and the claimable saving shrinks: (1−hit) + hit·cost."""
|
|
60
|
+
hit = min(max(cache_hit, 0.0), 1.0)
|
|
61
|
+
cost = min(max(cache_cost, 0.0), 1.0)
|
|
62
|
+
return (1.0 - hit) + hit * cost
|
|
63
|
+
|
|
64
|
+
|
|
65
|
+
def wh_from_tokens(tokens: float) -> tuple[float, float, float]:
|
|
66
|
+
"""Energy (Wh) for `tokens` at the declared low/mid/high coefficients."""
|
|
67
|
+
return tuple(tokens / 1e6 * KWH_PER_MTOK[k] * 1000.0 for k in ("low", "mid", "high")) # type: ignore[return-value]
|
|
68
|
+
|
|
69
|
+
|
|
70
|
+
def estimate_saving(tokens_saved: int, *, grid: str = "world",
|
|
71
|
+
cache_hit: float = 0.0, cache_cost: float = 0.10) -> Estimate:
|
|
72
|
+
"""Convert measured tokens saved into bounded Wh / gCO2e estimates."""
|
|
73
|
+
if grid not in GRID_GCO2_PER_KWH:
|
|
74
|
+
raise ValueError(f"unknown grid preset {grid!r}; options: {sorted(GRID_GCO2_PER_KWH)}")
|
|
75
|
+
mult = cache_multiplier(cache_hit, cache_cost)
|
|
76
|
+
wh = tuple(v * mult for v in wh_from_tokens(tokens_saved))
|
|
77
|
+
g = GRID_GCO2_PER_KWH[grid]
|
|
78
|
+
return Estimate(
|
|
79
|
+
tokens_saved=tokens_saved,
|
|
80
|
+
cache_multiplier=round(mult, 4),
|
|
81
|
+
wh=wh, # type: ignore[typeddict-item]
|
|
82
|
+
gco2e=tuple(v / 1000.0 * g for v in wh), # type: ignore[typeddict-item]
|
|
83
|
+
grid=grid,
|
|
84
|
+
kwh_per_mtok=dict(KWH_PER_MTOK),
|
|
85
|
+
)
|
|
86
|
+
|
|
87
|
+
|
|
88
|
+
def kpi_energy_per_token(tokens_before: int, tokens_after: int) -> dict:
|
|
89
|
+
"""The project KPI: energy per dispatch, before vs after apoptosis.
|
|
90
|
+
|
|
91
|
+
Returns Wh (low, mid, high) for both sides plus the reduction fraction —
|
|
92
|
+
which is exact (independent of the coefficient, since it cancels out)."""
|
|
93
|
+
if tokens_before <= 0:
|
|
94
|
+
raise ValueError("tokens_before must be positive")
|
|
95
|
+
return {
|
|
96
|
+
"wh_before": wh_from_tokens(tokens_before),
|
|
97
|
+
"wh_after": wh_from_tokens(tokens_after),
|
|
98
|
+
"reduction": 1.0 - tokens_after / tokens_before,
|
|
99
|
+
}
|
bioma/esg_report.py
ADDED
|
@@ -0,0 +1,123 @@
|
|
|
1
|
+
"""
|
|
2
|
+
`bioma/esg_report.py` — the design-partner instrument: turn a deployment's REAL
|
|
3
|
+
gateway audit log into a per-deployment ESG + cost case report.
|
|
4
|
+
|
|
5
|
+
The gateway writes one JSONL line per request (`tokens_before`, `tokens_after`,
|
|
6
|
+
`reduction`, kernel μs). This reads that ground-truth log and reports, for the
|
|
7
|
+
deployment: tokens avoided, and — via the declared literature coefficients in
|
|
8
|
+
`bioma.esg` — bounded Wh / gCO2e / USD avoided. Every input is measured on the
|
|
9
|
+
partner's own traffic; only the energy conversion is an estimate (with bounds).
|
|
10
|
+
|
|
11
|
+
A partner runs their real workload through the gateway, then:
|
|
12
|
+
|
|
13
|
+
python -m bioma.esg_report bioma_gateway_audit.jsonl --grid eu --price-in 2.0
|
|
14
|
+
|
|
15
|
+
No third-party data is invented here — the report is empty until a real log exists.
|
|
16
|
+
"""
|
|
17
|
+
from __future__ import annotations
|
|
18
|
+
|
|
19
|
+
import argparse
|
|
20
|
+
import json
|
|
21
|
+
import os
|
|
22
|
+
import sys
|
|
23
|
+
|
|
24
|
+
from bioma.esg import GRID_GCO2_PER_KWH, KWH_PER_MTOK, estimate_saving
|
|
25
|
+
|
|
26
|
+
|
|
27
|
+
def read_audit(path: str) -> list[dict]:
|
|
28
|
+
rows = []
|
|
29
|
+
with open(path, encoding="utf-8") as f:
|
|
30
|
+
for line in f:
|
|
31
|
+
line = line.strip()
|
|
32
|
+
if not line:
|
|
33
|
+
continue
|
|
34
|
+
try:
|
|
35
|
+
rows.append(json.loads(line))
|
|
36
|
+
except json.JSONDecodeError:
|
|
37
|
+
continue
|
|
38
|
+
return rows
|
|
39
|
+
|
|
40
|
+
|
|
41
|
+
def build_report(rows: list[dict], *, grid: str = "world",
|
|
42
|
+
price_in_per_mtok: float | None = None,
|
|
43
|
+
cache_hit: float = 0.0) -> dict:
|
|
44
|
+
n = len(rows)
|
|
45
|
+
before = sum(int(r.get("tokens_before", 0)) for r in rows)
|
|
46
|
+
after = sum(int(r.get("tokens_after", 0)) for r in rows)
|
|
47
|
+
saved = before - after
|
|
48
|
+
est = estimate_saving(saved, grid=grid, cache_hit=cache_hit) if saved > 0 else None
|
|
49
|
+
usd = None
|
|
50
|
+
if price_in_per_mtok is not None and saved > 0:
|
|
51
|
+
usd = saved / 1e6 * price_in_per_mtok
|
|
52
|
+
return {
|
|
53
|
+
"requests": n,
|
|
54
|
+
"tokens_before": before, "tokens_after": after, "tokens_saved": saved,
|
|
55
|
+
"reduction": (1 - after / before) if before else 0.0,
|
|
56
|
+
"grid": grid,
|
|
57
|
+
"wh_avoided": est["wh"] if est else (0.0, 0.0, 0.0),
|
|
58
|
+
"gco2e_avoided": est["gco2e"] if est else (0.0, 0.0, 0.0),
|
|
59
|
+
"usd_avoided": usd,
|
|
60
|
+
}
|
|
61
|
+
|
|
62
|
+
|
|
63
|
+
def render_md(rep: dict, coeff_note: str) -> str:
|
|
64
|
+
wl, wm, wh = rep["wh_avoided"]
|
|
65
|
+
gl, gm, gh = rep["gco2e_avoided"]
|
|
66
|
+
L = [
|
|
67
|
+
"# Relatório ESG de deployment — B.I.O.M.A. (dados do seu tráfego real)",
|
|
68
|
+
"",
|
|
69
|
+
f"> Gerado de {rep['requests']:,} requests do audit do gateway. Tokens = medidos "
|
|
70
|
+
"no seu tráfego; Wh/gCO2e = estimativa com coeficientes declarados "
|
|
71
|
+
f"({coeff_note}); limites baixo/central/alto.",
|
|
72
|
+
"",
|
|
73
|
+
"| Métrica | Valor |",
|
|
74
|
+
"| :--- | ---: |",
|
|
75
|
+
f"| Requests medidos | {rep['requests']:,} |",
|
|
76
|
+
f"| Tokens de entrada | {rep['tokens_before']:,} → {rep['tokens_after']:,} |",
|
|
77
|
+
f"| **Tokens evitados** | **{rep['tokens_saved']:,}** (−{rep['reduction']*100:.1f}%) |",
|
|
78
|
+
f"| Energia evitada (grid {rep['grid']}) | {wl:,.1f} / **{wm:,.1f}** / {wh:,.1f} Wh |",
|
|
79
|
+
f"| Emissões evitadas | {gl:,.1f} / **{gm:,.1f}** / {gh:,.1f} gCO2e |",
|
|
80
|
+
]
|
|
81
|
+
if rep["usd_avoided"] is not None:
|
|
82
|
+
L.append(f"| Custo de entrada evitado | **${rep['usd_avoided']:,.4f}** |")
|
|
83
|
+
L += ["",
|
|
84
|
+
"Escopo: redução auditável POR DEPLOYMENT (não global). A energia herda a "
|
|
85
|
+
"incerteza declarada do coeficiente; substitua pelo fator do seu grid/provedor.",
|
|
86
|
+
""]
|
|
87
|
+
return "\n".join(L)
|
|
88
|
+
|
|
89
|
+
|
|
90
|
+
def _main(argv: list[str] | None = None) -> int:
|
|
91
|
+
try:
|
|
92
|
+
sys.stdout.reconfigure(encoding="utf-8", errors="replace")
|
|
93
|
+
except Exception:
|
|
94
|
+
pass
|
|
95
|
+
ap = argparse.ArgumentParser(description="ESG deployment report from a gateway audit log.")
|
|
96
|
+
ap.add_argument("audit", help="path to bioma_gateway_audit.jsonl")
|
|
97
|
+
ap.add_argument("--grid", default="world", choices=sorted(GRID_GCO2_PER_KWH))
|
|
98
|
+
ap.add_argument("--price-in", type=float, default=None,
|
|
99
|
+
help="input price $/M tokens for your model (optional → $ avoided)")
|
|
100
|
+
ap.add_argument("--cache-hit", type=float, default=0.0)
|
|
101
|
+
ap.add_argument("--out", default=None, help="write the markdown report here")
|
|
102
|
+
args = ap.parse_args(argv)
|
|
103
|
+
if not os.path.exists(args.audit):
|
|
104
|
+
print(f"audit log não encontrado: {args.audit} — rode seu tráfego pelo gateway primeiro.")
|
|
105
|
+
return 2
|
|
106
|
+
rows = read_audit(args.audit)
|
|
107
|
+
if not rows:
|
|
108
|
+
print("audit vazio — nenhum request medido ainda.")
|
|
109
|
+
return 2
|
|
110
|
+
rep = build_report(rows, grid=args.grid, price_in_per_mtok=args.price_in,
|
|
111
|
+
cache_hit=args.cache_hit)
|
|
112
|
+
coeff = f"{KWH_PER_MTOK['low']}–{KWH_PER_MTOK['high']} kWh/Mtok, grid {args.grid}"
|
|
113
|
+
md = render_md(rep, coeff)
|
|
114
|
+
print(md)
|
|
115
|
+
if args.out:
|
|
116
|
+
with open(args.out, "w", encoding="utf-8") as f:
|
|
117
|
+
f.write(md)
|
|
118
|
+
print(f"📄 {args.out}")
|
|
119
|
+
return 0
|
|
120
|
+
|
|
121
|
+
|
|
122
|
+
if __name__ == "__main__":
|
|
123
|
+
raise SystemExit(_main())
|
bioma/firewall_client.py
ADDED
|
@@ -0,0 +1,223 @@
|
|
|
1
|
+
"""
|
|
2
|
+
`bioma/firewall_client.py` — the Cognitive Firewall: a local, provider-agnostic
|
|
3
|
+
defensive shim you drop in front of ANY LLM call (Anthropic, Google, OpenAI, …).
|
|
4
|
+
|
|
5
|
+
It is NOT a magic injection blocker. It is a stack of *real, measurable* controls:
|
|
6
|
+
|
|
7
|
+
1. **Secret redaction** — vault values are scrubbed from the outbound payload AND
|
|
8
|
+
the model response. An injection cannot exfiltrate a secret the model never got.
|
|
9
|
+
2. **Saturation detection + apoptosis** — cognitive-DDoS / floods are detected
|
|
10
|
+
(`saturation_scan`) → RED ALERT (`0x0F`) → dehydrated by apoptosis before dispatch.
|
|
11
|
+
3. **Timeout guard** — dispatch is bounded, so a loop/hang cannot stall the pipeline.
|
|
12
|
+
4. **Exponential backoff** — 429/5xx absorbed (built-in OpenRouter path).
|
|
13
|
+
|
|
14
|
+
Two ways to use it — 100% local, no hosted service:
|
|
15
|
+
|
|
16
|
+
fw = CognitiveFirewall(vault={"db": DB_PW})
|
|
17
|
+
|
|
18
|
+
# (a) PURE artifact — harden the payload, then call YOUR provider yourself:
|
|
19
|
+
h = fw.shield(history, "fix the bug")
|
|
20
|
+
# → send h.prompt / h.system to anthropic / google-genai / openai directly
|
|
21
|
+
# → h.telemetry has saturation, red_alert, apoptosis reduction, μs latency
|
|
22
|
+
|
|
23
|
+
# (b) Bring-your-own dispatcher (any async provider):
|
|
24
|
+
s = await fw.harden(history, "fix the bug", dispatch_fn=my_anthropic_call)
|
|
25
|
+
|
|
26
|
+
# (c) Convenience: built-in OpenRouter dispatch (needs OPENROUTER_API_KEY).
|
|
27
|
+
s = await fw.harden(history, "fix the bug", model="openai/gpt-4o")
|
|
28
|
+
"""
|
|
29
|
+
from __future__ import annotations
|
|
30
|
+
|
|
31
|
+
import asyncio
|
|
32
|
+
import os
|
|
33
|
+
import random
|
|
34
|
+
from dataclasses import dataclass
|
|
35
|
+
from typing import Awaitable, Callable, Optional
|
|
36
|
+
|
|
37
|
+
import bioma_micro as _kernel
|
|
38
|
+
|
|
39
|
+
RED_ALERT = 0x0F # invasion bit-flag broadcast on the hormonal bus
|
|
40
|
+
OPENROUTER_BASE_URL = "https://openrouter.ai/api/v1"
|
|
41
|
+
|
|
42
|
+
_ROLE_SIGNAL = {"system": _kernel.SYSTEM, "user": _kernel.USER, "assistant": _kernel.ASSISTANT,
|
|
43
|
+
"tool": _kernel.TOOL, "fact": _kernel.FACT}
|
|
44
|
+
|
|
45
|
+
# A bring-your-own dispatcher: takes the hardened (prompt, system) and returns text.
|
|
46
|
+
Dispatcher = Callable[[str, Optional[str]], Awaitable[str]]
|
|
47
|
+
|
|
48
|
+
|
|
49
|
+
@dataclass
|
|
50
|
+
class Hardened:
|
|
51
|
+
"""The pure output of `shield()`: a clean payload ready for ANY provider."""
|
|
52
|
+
prompt: str # dehydrated + redacted user payload
|
|
53
|
+
system: Optional[str] # redacted system prompt
|
|
54
|
+
saturation: float
|
|
55
|
+
red_alert: bool
|
|
56
|
+
secrets_redacted: int
|
|
57
|
+
outbound_clean: bool # no vault secret survived into the outbound
|
|
58
|
+
apoptosis_reduction: float
|
|
59
|
+
tokens_before: int
|
|
60
|
+
tokens_after: int
|
|
61
|
+
kernel_latency_us: float
|
|
62
|
+
|
|
63
|
+
@property
|
|
64
|
+
def telemetry(self) -> dict:
|
|
65
|
+
return {"saturation": self.saturation, "red_alert": self.red_alert,
|
|
66
|
+
"secrets_redacted": self.secrets_redacted, "outbound_clean": self.outbound_clean,
|
|
67
|
+
"apoptosis_reduction": self.apoptosis_reduction, "tokens_before": self.tokens_before,
|
|
68
|
+
"tokens_after": self.tokens_after, "kernel_latency_us": self.kernel_latency_us}
|
|
69
|
+
|
|
70
|
+
|
|
71
|
+
@dataclass
|
|
72
|
+
class Shield:
|
|
73
|
+
"""The outcome of one hardened *dispatch* + full defensive telemetry."""
|
|
74
|
+
answer: str
|
|
75
|
+
model: str
|
|
76
|
+
saturation: float
|
|
77
|
+
red_alert: bool
|
|
78
|
+
secrets_redacted: int
|
|
79
|
+
outbound_clean: bool
|
|
80
|
+
apoptosis_reduction: float
|
|
81
|
+
tokens_before: int
|
|
82
|
+
tokens_after: int
|
|
83
|
+
kernel_latency_us: float
|
|
84
|
+
dispatched: bool
|
|
85
|
+
timed_out: bool
|
|
86
|
+
error: Optional[str] = None
|
|
87
|
+
|
|
88
|
+
|
|
89
|
+
class CognitiveFirewall:
|
|
90
|
+
"""Local, provider-agnostic defensive shim. Thread-safe: kernel calls are pure."""
|
|
91
|
+
|
|
92
|
+
def __init__(self, api_key: Optional[str] = None, *, vault: Optional[dict] = None,
|
|
93
|
+
saturation_threshold: float = 0.85, dispatch_timeout: float = 20.0,
|
|
94
|
+
max_retries: int = 5, base_delay: float = 1.0, max_delay: float = 30.0,
|
|
95
|
+
half_life: float = 6.0, safe_threshold: float = 0.35,
|
|
96
|
+
referer: str = "https://bioma.ai", title: str = "B.I.O.M.A. Cognitive Firewall"):
|
|
97
|
+
self._vault = dict(vault or {})
|
|
98
|
+
self._secrets = [str(v) for v in self._vault.values() if v]
|
|
99
|
+
self.saturation_threshold = saturation_threshold
|
|
100
|
+
self.dispatch_timeout = dispatch_timeout
|
|
101
|
+
self.max_retries = max_retries
|
|
102
|
+
self.base_delay = base_delay
|
|
103
|
+
self.max_delay = max_delay
|
|
104
|
+
self.half_life = half_life
|
|
105
|
+
self.safe_threshold = safe_threshold
|
|
106
|
+
self._bus = _kernel.HormonalBus(32)
|
|
107
|
+
key = api_key or os.environ.get("OPENROUTER_API_KEY")
|
|
108
|
+
self.online = bool(key and key.startswith("sk-or"))
|
|
109
|
+
if self.online:
|
|
110
|
+
from openai import AsyncOpenAI
|
|
111
|
+
self._client = AsyncOpenAI(base_url=OPENROUTER_BASE_URL, api_key=key,
|
|
112
|
+
default_headers={"HTTP-Referer": referer, "X-Title": title})
|
|
113
|
+
else:
|
|
114
|
+
self._client = None
|
|
115
|
+
|
|
116
|
+
# ----- primitives ------------------------------------------------------ #
|
|
117
|
+
def _redact(self, text: str) -> tuple[str, int]:
|
|
118
|
+
hits = 0
|
|
119
|
+
for sv in self._secrets:
|
|
120
|
+
if sv and sv in text:
|
|
121
|
+
hits += text.count(sv)
|
|
122
|
+
text = text.replace(sv, "[REDACTED]")
|
|
123
|
+
return text, hits
|
|
124
|
+
|
|
125
|
+
def _leaks(self, text: str) -> bool:
|
|
126
|
+
return any(sv in text for sv in self._secrets if sv)
|
|
127
|
+
|
|
128
|
+
def scan(self, text: str) -> float:
|
|
129
|
+
"""Cognitive-DDoS saturation score (0..1)."""
|
|
130
|
+
return _kernel.saturation_scan(text)
|
|
131
|
+
|
|
132
|
+
def alert_level(self) -> float:
|
|
133
|
+
return self._bus.sense(RED_ALERT)
|
|
134
|
+
|
|
135
|
+
# ----- the PURE hardening primitive (provider-agnostic) ---------------- #
|
|
136
|
+
def shield(self, history: list[dict], query: str, system: Optional[str] = None) -> Hardened:
|
|
137
|
+
"""Harden a payload — scan → RED ALERT → apoptosis → secret redaction — and
|
|
138
|
+
return the clean prompt/system + telemetry. No network, no provider. Send the
|
|
139
|
+
result to Anthropic / Google / OpenAI (or anything) yourself."""
|
|
140
|
+
payload = "\n".join(str(m.get("content", "")) for m in history) + "\n" + query
|
|
141
|
+
saturation = _kernel.saturation_scan(payload)
|
|
142
|
+
red = saturation >= self.saturation_threshold
|
|
143
|
+
if red:
|
|
144
|
+
self._bus.secrete(RED_ALERT, min(1.0, saturation))
|
|
145
|
+
|
|
146
|
+
msgs = [(str(m.get("content", "")), _ROLE_SIGNAL.get(m.get("role", "user"), _kernel.USER))
|
|
147
|
+
for m in history]
|
|
148
|
+
audit = _kernel.dehydrate(msgs, half_life=self.half_life, safe_threshold=self.safe_threshold)
|
|
149
|
+
dehydrated = "\n".join(audit["kept"])
|
|
150
|
+
|
|
151
|
+
clean_ctx, h1 = self._redact(dehydrated)
|
|
152
|
+
clean_query, h2 = self._redact(query)
|
|
153
|
+
clean_system, h3 = self._redact(system) if system else ("", 0)
|
|
154
|
+
prompt = f"Context:\n{clean_ctx}\n\nRequest:\n{clean_query}" if clean_ctx else clean_query
|
|
155
|
+
outbound_clean = not (self._leaks(prompt) or self._leaks(clean_system))
|
|
156
|
+
return Hardened(prompt=prompt, system=(clean_system or None), saturation=round(saturation, 4),
|
|
157
|
+
red_alert=red, secrets_redacted=h1 + h2 + h3, outbound_clean=outbound_clean,
|
|
158
|
+
apoptosis_reduction=float(audit["reduction"]), tokens_before=int(audit["tokens_before"]),
|
|
159
|
+
tokens_after=int(audit["tokens_after"]), kernel_latency_us=float(audit["kernel_latency_us"]))
|
|
160
|
+
|
|
161
|
+
# ----- hardened dispatch (built-in OpenRouter OR your own provider) ---- #
|
|
162
|
+
async def harden(self, history: list[dict], query: str, *, model: str = "openai/gpt-4o",
|
|
163
|
+
system: Optional[str] = None, max_tokens: int = 256,
|
|
164
|
+
timeout: Optional[float] = None,
|
|
165
|
+
dispatch_fn: Optional[Dispatcher] = None) -> Shield:
|
|
166
|
+
hp = self.shield(history, query, system)
|
|
167
|
+
base = dict(saturation=hp.saturation, red_alert=hp.red_alert, secrets_redacted=hp.secrets_redacted,
|
|
168
|
+
outbound_clean=hp.outbound_clean, apoptosis_reduction=hp.apoptosis_reduction,
|
|
169
|
+
tokens_before=hp.tokens_before, tokens_after=hp.tokens_after,
|
|
170
|
+
kernel_latency_us=hp.kernel_latency_us)
|
|
171
|
+
bound = timeout if timeout is not None else self.dispatch_timeout
|
|
172
|
+
|
|
173
|
+
# No dispatcher available → hardening ran, dispatch skipped.
|
|
174
|
+
if dispatch_fn is None and not self.online:
|
|
175
|
+
return Shield(answer="", model=model, dispatched=False, timed_out=False,
|
|
176
|
+
error="offline (no key, no dispatch_fn) — defenses ran; dispatch skipped", **base)
|
|
177
|
+
|
|
178
|
+
try:
|
|
179
|
+
if dispatch_fn is not None: # bring-your-own provider (Anthropic/Google/OpenAI)
|
|
180
|
+
text = await asyncio.wait_for(dispatch_fn(hp.prompt, hp.system), timeout=bound)
|
|
181
|
+
err = None
|
|
182
|
+
model = "custom"
|
|
183
|
+
else: # built-in OpenRouter convenience
|
|
184
|
+
messages = ([{"role": "system", "content": hp.system}] if hp.system else []) + \
|
|
185
|
+
[{"role": "user", "content": hp.prompt}]
|
|
186
|
+
text, err = await asyncio.wait_for(self._dispatch(model, messages, max_tokens), timeout=bound)
|
|
187
|
+
except asyncio.TimeoutError:
|
|
188
|
+
return Shield(answer="", model=model, dispatched=False, timed_out=True,
|
|
189
|
+
error=f"dispatch exceeded {bound}s — contained by timeout guard", **base)
|
|
190
|
+
|
|
191
|
+
safe_answer, resp_hits = self._redact(text or "")
|
|
192
|
+
base["secrets_redacted"] += resp_hits
|
|
193
|
+
base["outbound_clean"] = base["outbound_clean"] and not self._leaks(safe_answer)
|
|
194
|
+
return Shield(answer=safe_answer, model=model, dispatched=(err is None),
|
|
195
|
+
timed_out=False, error=err, **base)
|
|
196
|
+
|
|
197
|
+
async def _dispatch(self, model: str, messages: list, max_tokens: int) -> tuple[str, Optional[str]]:
|
|
198
|
+
from openai import (APIConnectionError, APIStatusError, APITimeoutError, RateLimitError)
|
|
199
|
+
delay, last = self.base_delay, "unknown"
|
|
200
|
+
for attempt in range(self.max_retries + 1):
|
|
201
|
+
try:
|
|
202
|
+
resp = await self._client.chat.completions.create(
|
|
203
|
+
model=model, messages=messages, max_tokens=max_tokens,
|
|
204
|
+
temperature=0.2, extra_body={"usage": {"include": True}})
|
|
205
|
+
return resp.choices[0].message.content or "", None
|
|
206
|
+
except RateLimitError as exc:
|
|
207
|
+
last = f"429 {exc}"
|
|
208
|
+
except APIStatusError as exc:
|
|
209
|
+
code = getattr(exc, "status_code", 0)
|
|
210
|
+
if 500 <= code < 600:
|
|
211
|
+
last = f"{code} {exc}"
|
|
212
|
+
else:
|
|
213
|
+
return "", f"{code}: {exc}"
|
|
214
|
+
except (APIConnectionError, APITimeoutError) as exc:
|
|
215
|
+
last = f"conn {exc}"
|
|
216
|
+
if attempt < self.max_retries:
|
|
217
|
+
await asyncio.sleep(min(self.max_delay, delay) + random.uniform(0, 0.3 * delay))
|
|
218
|
+
delay *= 2
|
|
219
|
+
return "", f"exhausted retries: {last}"
|
|
220
|
+
|
|
221
|
+
async def close(self) -> None:
|
|
222
|
+
if self._client is not None:
|
|
223
|
+
await self._client.close()
|