Skip to content

Explainability API

Two interfaces, and for almost every integration only one of them matters. The black-box endpoint on G1-Proxy attributes a verdict to the tokens that caused it without touching model internals — that is the production path. The inline explain flag on the Studio-local evaluate endpoint needs a checkpoint loaded in-process and belongs to research work.


Call it

What it does. Send a prompt, an answer and optionally the grounding context; get back the tokens that caused the detector's verdict, with a certificate of how strongly. Deterministic — same input, same build, same answer.

curl -s -X POST http://localhost:8080/gw/v1/glad/causal-explainability/analyze \
  -H "Content-Type: application/json" \
  -d '{
    "prompt":   "According to the document, when was the Eiffel Tower built?",
    "context":  "The Eiffel Tower was constructed between 1887 and 1889.",
    "response": "The Eiffel Tower was built in 1885.",
    "method":   "dca",
    "axis":     "halluc_context"
  }' | jq '{
    axis: .detection_type,
    base: .base_score,
    mode: .xai.gradient_causal.attribution_mode,
    necessary: .xai.gradient_causal.necessary_tokens
  }'
import httpx

r = httpx.post(
    "http://localhost:8080/gw/v1/glad/causal-explainability/analyze",
    json={
        "prompt":   "According to the document, when was the Eiffel Tower built?",
        "context":  "The Eiffel Tower was constructed between 1887 and 1889.",
        "response": "The Eiffel Tower was built in 1885.",
        "method":   "dca",
        "axis":     "halluc_context",
    },
    timeout=360,
)
r.raise_for_status()
dca = r.json()["xai"]["gradient_causal"]
print(dca["attribution_mode"], dca["base_score"])
for tok in dca["top_tokens"]:
    print(f"  {tok['token']!r:12s} {tok['status']:10s} effect={tok['effect']:.2f}")
const res = await fetch(
  "http://localhost:8080/gw/v1/glad/causal-explainability/analyze",
  {
    method: "POST",
    headers: { "Content-Type": "application/json" },
    body: JSON.stringify({
      prompt: "According to the document, when was the Eiffel Tower built?",
      context: "The Eiffel Tower was constructed between 1887 and 1889.",
      response: "The Eiffel Tower was built in 1885.",
      method: "dca",
      axis: "halluc_context",
    }),
  },
)
if (!res.ok) throw new Error(await res.text())
const dca = (await res.json()).xai.gradient_causal
console.log(dca.attribution_mode, dca.necessary_tokens)

What comes back

{
  "prompt": "According to the document, when was the Eiffel Tower built?",
  "full_response": "The Eiffel Tower was built in 1885.",
  "detection_type": "halluc_context",
  "base_score": 0.71,
  "xai": {
    "method": "dca",
    "gradient_causal": {
      "attribution_mode": "certified",
      "certificate_basis": "necessity",
      "base_score": 0.71,
      "sufficiency_bar": 0.639,
      "n_forward": 16,
      "top_tokens": [
        { "token": "1885", "position": 6, "region": "answer", "status": "necessary",
          "effect": 0.62, "sufficiency": 0.55, "responsibility": 1.0 }
      ],
      "necessary_tokens": ["1885"]
    }
  }
}

"1885" is the certified necessary token: remove it alone and the faithfulness score drops below the flag.

Methods

method What it computes Latency
dca (default) Deterministic attribution on the dominant flagged axis. ~1–3 s
dca_dual Prompt and answer surfaces attributed separately. The only method that accepts an empty response — a prompt blocked before generation has no answer. ~1–3 s
gradient_causal / occlusion Leave-one-out occlusion. seconds
mupax_causal Monte-Carlo coalition estimation. Accepts mupax_n_samples. minutes

Full field-by-field reference, attribution modes and the certificate semantics: Causal Explainability.


Inline explain — Studio-local, research only

POST /glad/evaluate on G-1 Studio's own port accepts explain: true and returns attribution in the response's xai field. It requires a research checkpoint loaded in-process, and in the packaged product the Studio backend runs without one — so this is not the path to build on. Use the black-box endpoint above.

Parameters

Parameter Description
explain true to compute attribution.
explain_mode "standard" (default) or "causal".
credit_tiers Which attribution methods to run — see below.
system_prompt_text When given, its tokens are excluded from attribution.

Credit tiers

Tier Key Speed Description
1 "gradient" ~50 ms Deterministic prompt-token occlusion: mask one token at a time, the score change is the importance.
1.5 "pss" ~N× generation Positional Semantic Stability — see below.
2 "mupax" ~0.4–2 s Coalition estimation: random coalitions scored with the detector, fitted with one joint linear surrogate whose coefficients are the per-unit attribution. Accounts for interactions. Seeded, so it reproduces exactly.
3 "learned" ~10 ms Learned attribution head, when the checkpoint has one. Fastest; accuracy depends on training coverage.
{
  "model_path": "/app/pretrained_glad",
  "prompt": "When was the Eiffel Tower built?",
  "explain": true,
  "credit_tiers": ["mupax", "gradient"]
}

explain_mode: "causal"

Additionally computes a token→token causal matrix: for the answer token with the highest attribution, which prompt tokens are causally responsible for it. Not what words mattered, but which prompt words caused the model to write the most suspicious part of the answer.

Response structure

"xai": {
  "mupax_halluc": {
    "detection_type": "hallucination",
    "top_tokens": [
      { "token": "Paris", "position": 7, "importance": 0.48,
        "retention_frequency": 0.71, "conditional_goodness": 0.88 }
    ],
    "threshold_W": 0.14,
    "threshold_percentile_used": 0.2,
    "n_accepted": 412,
    "n_total": 500,
    "attribution_heatmap": [0.02, 0.01, 0.48, 0.12],
    "score_function": "combined_logreg"
  },
  "mupax_halluc_causal": {
    "target_token": "1889",
    "target_position": 14,
    "causal_edges": [
      { "source_position": 4, "source_token": "built",
        "target_position": 14, "target_token": "1889",
        "raw_importance": 0.61, "normalized_importance": 0.83, "absolute_importance": 0.83 }
    ]
  }
}
Per-token field Description
token Token text as decoded from the vocabulary.
position Position in the full input sequence.
importance Attribution value. Higher = contributed more to the detection score.
retention_frequency Share of Monte-Carlo samples where this token appeared in above-threshold configurations.
conditional_goodness Mean detection score when this token was present.
Causal-edge field Description
source_position / source_token The prompt token.
target_position / target_token The answer token.
raw_importance Signed importance; positive = causal contribution.
normalized_importance Signed, normalised by the largest absolute value in the graph.
absolute_importance Absolute normalised importance, [0,1].

PSS — Positional Semantic Stability

A training-free method that asks a different question: if I change the prompt here, does the key claim in the answer change? It needs no gradients and no weights — it generates N alternative answers and measures which claims survive.

Parameter Env override Default Description
pss_n_samples GLAD_PSS_N_SAMPLES 5 Extra samples to generate. Each costs one generation pass. 2 = fast/noisy, 16 = slow/robust.
pss_temperature GLAD_PSS_TEMPERATURE 0.7 Must be > 0 — at 0 every sample would be identical.
pss_match_mode GLAD_PSS_MATCH_MODE "ngram" How claims are compared: ngram (containment + entity match), strict (exact surface), fuzzy (Levenshtein), entity, claim (sentence-level bidirectional).

Reach for it when you are explaining hallucination in long-form answers where occlusion is noisy, you need attribution with no access to weights at all, or you are building a human review workflow and the explanation has to be relatable — "this claim changed when we removed that context sentence".