Skip to content

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 03 (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.