Generic Evaluation API V1¶
Die Generic Evaluation API gleicht temporäre symbolische Signale deterministisch mit vertrauensfähigen Evaluationsregeln im bestehenden FragmentStore ab.
Die Schnittstelle ist generisch. Sie kann beispielsweise Interaktionen, technische Zustände, Risiken, Prozesse, Qualität oder Maschinenzustände auswerten. Sie enthält keine emotionsspezifische Logik.
Funktionsgrenze¶
Der Ablauf ist fest:
- Request validieren.
- Domain-Namespace
evaluation:<domain>im FragmentStore lesen. - Nur Regeln verwenden, die den bestehenden Trust-/Stability-Gate bestehen.
- Alle
requires-Terme exakt abgleichen. - Regeln mit zutreffendem
excludesblockieren. - Vertrauensfähige explizite
contrast-Relationen prüfen. concludes-Outcomes exakt filtern.- Ergebnisse und Proof deterministisch sortieren.
Die Evaluation:
- schreibt keine Fragmente, Kandidaten, Patterns oder Erinnerungen;
- verändert keine Support-, Resonanz- oder Stability-Werte;
- ruft kein LLM, Ollama oder einen externen Dienst auf;
- interpretiert keine Rohtexte, Synonyme, Negationen oder Ähnlichkeiten;
- verwendet
requested_outcomesnur als exakten Filter.
Keine Regeln aus Request-Daten
Signale existieren nur für die Dauer des Requests. Sie werden nicht gespeichert und erzeugen keine neuen Regeln oder Kandidaten.
Authentifizierung¶
Der Endpoint erfordert einen gültigen Bearer-Key:
Fehlende oder ungültige Keys ergeben HTTP 401. Der Endpoint verwendet dasselbe benutzerbezogene Rate-Limit wie die bestehende API; eine Überschreitung ergibt HTTP 429.
Request¶
{
"domain": "interaction_analysis",
"evaluation_type": "hypothesis_match",
"signals": [
{
"id": "signal-1",
"term": "friction:high",
"evidence_refs": ["feature:friction"]
},
{
"id": "signal-2",
"term": "certainty:low",
"evidence_refs": ["feature:certainty"]
},
{
"id": "signal-3",
"term": "engagement:medium_or_high",
"evidence_refs": ["feature:engagement"]
}
],
"requested_outcomes": [
"hypothesis:confusion",
"hypothesis:frustration"
]
}
Request-Felder¶
| Feld | Pflicht | Grenze | Funktion |
|---|---|---|---|
domain |
ja | 64 Zeichen | Wird getrimmt und kleingeschrieben; bestimmt evaluation:<domain> |
evaluation_type |
ja | fester Wert | In V1 ausschließlich hypothesis_match |
signals |
ja | 1 bis 200 | Temporäre symbolische Signale |
signals[].id |
ja | 128 Zeichen | Innerhalb des Requests eindeutig |
signals[].term |
ja | 256 Zeichen | Exakter symbolischer Term wie temperature:high |
signals[].evidence_refs |
nein | maximal 20 | Symbolische Belegreferenzen; keine Metadatenobjekte |
requested_outcomes |
nein | 1 bis 200 | Exakte Outcome-Filter; erzeugen keine Outcomes |
Unbekannte Felder, Rohtextfelder, numerische Signalwerte, doppelte Signal-IDs und mehr als 200 Signale werden mit HTTP 422 abgelehnt. Die maximale Requestgröße beträgt 1 MiB; größere Requests ergeben HTTP 413.
Listenreihenfolgen bleiben Bestandteil des kanonischen Request-Hashes. Objektschlüssel werden für den Hash sortiert.
Erfolgreiche Response¶
{
"status": "evaluated",
"engine_version": "evaluation-v1",
"request_hash": "sha256-hexwert",
"results": [
{
"outcome": "hypothesis:confusion",
"rule_fragment_id": "frag:evaluation:interaction-confusion-v1",
"support_floor": 0.63,
"matched_signal_ids": ["signal-1", "signal-2", "signal-3"],
"evidence_refs": [
"feature:certainty",
"feature:engagement",
"feature:friction"
],
"proof": {
"requires": [
{"signal_id": "signal-2", "term": "certainty:low"},
{"signal_id": "signal-3", "term": "engagement:medium_or_high"},
{"signal_id": "signal-1", "term": "friction:high"}
],
"conclusion_relation": {
"from": "interaction.confusion.v1",
"relation": "concludes",
"to": "hypothesis:confusion"
},
"fragment_ids": ["frag:evaluation:interaction-confusion-v1"]
}
}
],
"unknown_reasons": []
}
support_floor wird nur aus einem real gespeicherten numerischen stability_score übernommen. Der Wert wird nicht umgerechnet und ist keine Wahrscheinlichkeit. Ohne gespeicherten Wert ist das Feld null.
Unknown-Response¶
Wenn kein Ergebnis belegbar ist, bleibt HTTP 200; der fachliche Status lautet unknown:
{
"status": "unknown",
"engine_version": "evaluation-v1",
"request_hash": "sha256-hexwert",
"results": [],
"unknown_reasons": ["domain_not_found"]
}
Mögliche Gründe:
| Grund | Bedeutung |
|---|---|
insufficient_signals |
Mindestens ein erforderlicher Term fehlt |
no_eligible_rule |
Keine strukturell ausführbare Regel passt |
rule_below_trust_gate |
Regeln existieren, bestehen aber den bestehenden Trust-Gate nicht |
contradictory_signals |
Eine vertrauensfähige explizite contrast-Relation trifft zu |
requested_outcome_not_supported |
Passende Regeln schließen keines der angefragten Outcomes |
domain_not_found |
Der Namespace evaluation:<domain> existiert nicht |
Es werden keine freien Erklärungstexte oder geratenen Outcomes erzeugt.
curl¶
export LENNY_API_KEY="sk-lenny-DEIN-KEY"
curl --fail-with-body -sS \
-X POST "https://lenny-api.mycubeserver.com/v1/evaluations" \
-H "Authorization: Bearer ${LENNY_API_KEY}" \
-H "Content-Type: application/json" \
--data-binary @evaluation-request.json \
| python3 -m json.tool
Python¶
import json
import os
import urllib.request
payload = {
"domain": "operations",
"evaluation_type": "hypothesis_match",
"signals": [
{"id": "sensor-1", "term": "temperature:high", "evidence_refs": []},
{"id": "sensor-2", "term": "pressure:high", "evidence_refs": []},
],
"requested_outcomes": ["action:inspection_required"],
}
request = urllib.request.Request(
"https://lenny-api.mycubeserver.com/v1/evaluations",
data=json.dumps(payload, separators=(",", ":")).encode("utf-8"),
headers={
"Authorization": f"Bearer {os.environ['LENNY_API_KEY']}",
"Content-Type": "application/json",
},
method="POST",
)
with urllib.request.urlopen(request, timeout=30) as response:
result = json.load(response)
print(result["status"])
print(result["results"])
Regelrepräsentation¶
Regeln sind normale Fragmente im bestehenden FragmentStore. V1 interpretiert ausschließlich:
requires: jeder Term muss exakt in den Request-Signalen vorhanden sein;excludes: ein vorhandener Term blockiert die Regel;concludes: erzeugt ein Outcome, sofern die Regel vollständig passt.
Ein Namespace oder eine Regel-ID erteilt keine Sonderfreigabe. Nur der unveränderte bestehende Trust-/Stability-Pfad entscheidet, ob eine gespeicherte Regel ausgeführt werden darf. Das Anlegen oder Freigeben produktiver Regeln ist ein separater administrativer Vorgang und nicht Teil dieses Endpoints.
Regeln trainieren¶
Evaluation-Regeln werden nicht durch Evaluation-Requests gelernt. Sie muessen als
Kandidaten-Fragmente in den FragmentStore importiert werden, z.B. ueber den
Admin-Endpunkt POST /v1/admin/fragment_training.
Auch dieser Import setzt keine Wahrheit:
Eine Regel wird erst ausgefuehrt, wenn der bestehende Trust-/Stability-Gate sie traegt. Fuer den Betrieb ist die interne Admin-Doku "Fragment Training API V1" massgeblich.