Evaluate Endpoint¶
What it does. POST /v1/glad/evaluate on G1-Proxy generates an answer from your upstream LLM and scores it, in one HTTP round-trip. It is the batch-workflow twin of the Chat API: same pipeline, same detection, but you send a bare prompt instead of a message array and you get the full detection payload back rather than a chat-shaped body.
Reach for it when you are scoring a corpus, running an offline evaluation, or wiring detection into something that is not a chat client.
Call it¶
curl -s http://localhost:8080/gw/v1/glad/evaluate \
-H "Content-Type: application/json" \
-H "X-Geodesia-App: support_bot" \
-d '{
"model": "my-model",
"prompt": "How tall is the Eiffel Tower?",
"context": "The Eiffel Tower was built between 1887 and 1889 and stands 330 metres tall."
}' | jq '{
answer: .choices[0].message.content,
decision: .glad_decision,
axes: .geodesia.axis_energy
}'
import httpx
rows = [
{"prompt": "How tall is the Eiffel Tower?",
"context": "The Eiffel Tower … stands 330 metres tall."},
{"prompt": "Summarise our refund policy.", "context": ""},
]
with httpx.Client(base_url="http://localhost:8080/gw",
headers={"X-Geodesia-App": "support_bot"},
timeout=120) as c:
for row in rows:
r = c.post("/v1/glad/evaluate", json={"model": "my-model", **row}).json()
axes = r["geodesia"]["axis_energy"]
flagged = [a for a, e in axes.items() if e.get("flag")]
print(f"{r['glad_decision']:8s} flagged={flagged or '-'} {row['prompt'][:40]}")
const rows = [
{ prompt: "How tall is the Eiffel Tower?", context: "…stands 330 metres tall." },
{ prompt: "Summarise our refund policy.", context: "" },
]
for (const row of rows) {
const r = await fetch("http://localhost:8080/gw/v1/glad/evaluate", {
method: "POST",
headers: { "Content-Type": "application/json", "X-Geodesia-App": "support_bot" },
body: JSON.stringify({ model: "my-model", ...row }),
}).then(r => r.json())
const flagged = Object.entries(r.geodesia.axis_energy)
.filter(([, e]: any) => e.flag)
.map(([a]) => a)
console.log(r.glad_decision, flagged, row.prompt.slice(0, 40))
}
What comes back¶
An OpenAI-shaped body carrying the full detection payload — the same structure the Chat API returns:
{
"choices": [
{ "index": 0,
"message": { "role": "assistant", "content": "It stands 330 metres tall." },
"finish_reason": "stop" }
],
"glad_decision": "passed",
"glad_mode": "blocking",
"geodesia": {
"axis_energy": {
"halluc_context": { "p_detector": 0.07, "flag": false, "threshold": 0.6475, "available": true },
"halluc_closedbook": { "p_detector": 0.04, "flag": false, "threshold": 0.58, "available": true },
"prompt_safety": { "p_detector": 0.01, "flag": false, "threshold": 0.9215, "available": true },
"answer_safety": { "p_detector": 0.02, "flag": false, "threshold": 0.7295, "available": true },
"jailbreak": { "p_detector": 0.00, "flag": false, "threshold": 0.9997, "available": true },
"rag_jailbreak": { "p_detector": 0.03, "flag": false, "threshold": 0.2501, "available": true },
"profanity": { "p_detector": 0.00, "flag": false, "threshold": 0.90, "available": true },
"out_of_scope": { "p_detector": 0.02, "flag": false, "threshold": 0.90, "available": true },
"prompt_complexity": { "p_detector": 0.18, "flag": false, "threshold": 0.50, "available": true }
},
"brake": false,
"dominant_axis": "prompt_complexity"
}
}
Never streamed: this endpoint always returns a single JSON body, whatever stream you send.
Request reference¶
| Field | Type | Required | Description |
|---|---|---|---|
prompt | string | ✅¹ | The input to score. |
messages | array | ✅¹ | An OpenAI message array, if you would rather send conversation shape. Wins over prompt when both are present. |
model | string | — | Defaults to the Application's binding, or the gateway's configured model. |
context | string | — | Grounding text. Drives the halluc_context axis and is injected into the generation. |
rag | object | — | Retrieve the context instead of supplying it: {collection_id, top_k, rerank, verify}. |
mode / glad_mode | string | — | block or passthrough for this call. |
threshold_overrides | object | — | Per-axis thresholds. Only the five base axes are honoured — see Chat API. |
thinking_level | integer | — | 0–3 (3 = MAX). See Thinking Levels. |
domain | string | — | Domain-conditional calibration bucket for the closed-book axis. |
application_id / app_id | string | — | Same as the X-Geodesia-App header. |
pii_guard | boolean | — | Per-request PII redaction override. |
¹ Send one of prompt or messages. Everything else on the body that is not a Geodesia control field is forwarded to the upstream as a generation parameter.
pass_extra is fixed at 1 here
Unlike the chat endpoint, /v1/glad/evaluate always runs a single generation pass. If you want closed-book self-consistency sampling, use POST /v1/chat/completions with pass_extra or self_consistency.
Scoring without generating¶
If you already have both the prompt and the answer and only want them scored — replaying stored traffic, evaluating another system's output, testing a threshold change — do not use this endpoint: it will generate a fresh answer. Use the attribution endpoint instead, which scores text you supply:
curl -s http://localhost:8080/gw/v1/glad/causal-explainability/analyze \
-H "Content-Type: application/json" \
-d '{
"prompt": "How tall is the Eiffel Tower?",
"response": "It is 1200 metres tall and located in Berlin.",
"context": "The Eiffel Tower … stands 330 metres tall.",
"method": "dca"
}'
See Explainability and Causal Explainability.
Studio-local research endpoints¶
G-1 Studio also exposes an older, local-model evaluation surface at /glad/evaluate, /glad/export_audit and /glad/finetune. These are mounted outside /v1, so the unified port on 8080 does not route to them — they are reachable only on Studio's own port (:8199 by default) and they require a research checkpoint loaded in-process. In the packaged product the Studio backend runs without a GPU model, so they are not the path to build on.
| Method | Path | What it does |
|---|---|---|
POST | /glad/evaluate | Generate + score against the locally loaded checkpoint. Body: {model_path, prompt, context?, generation_config?, session_id?, explain?, credit_tiers?, threshold_overrides?, …}. |
POST | /glad/export_audit | Export an audit bundle. Body: {session_id \| call_ids, client_info?, regulatory_framework?, include_raw_scores?, include_compliance_bundle?, output_path?}. |
POST | /glad/finetune | Submit a fine-tuning job. 202 with a job_id. |
GET | /glad/finetune/status/{job_id} | {job_id, status, progress?, current_step?, total_steps?, last_loss?, output_path?, error?}. status is queued | running | completed | failed; 404 on an unknown job. |
For anything production, use POST /v1/glad/evaluate on G1-Proxy — it scores against your real upstream, honours Application policy, and writes to the compliance ledger.