Skip to content

Anti-hallucination: 5-layer grounding layer (quote verify, trigger va…#5

Merged
Vector897 merged 1 commit into
mainfrom
feat/gcp-integration
Jun 27, 2026
Merged

Anti-hallucination: 5-layer grounding layer (quote verify, trigger va…#5
Vector897 merged 1 commit into
mainfrom
feat/gcp-integration

Conversation

@Vector897

Copy link
Copy Markdown
Owner

…lidate, majority-vote referee, score clamp, schema guard) (2026-06-27)

…lidate, majority-vote referee, score clamp, schema guard) (2026-06-27)
Copilot AI review requested due to automatic review settings June 27, 2026 16:30
@Vector897
Vector897 merged commit d6c5ef0 into main Jun 27, 2026
1 check passed

Copilot AI left a comment

Copy link
Copy Markdown

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Pull request overview

This PR introduces a new “grounding” layer in the backend engines to reduce LLM hallucinations and enforce safer, more consistent structured outputs for adversary and scoring responses.

Changes:

  • Added backend/app/engines/grounding.py implementing quote verification, trigger validation, self-consistency voting, score clamping, and schema guards.
  • Integrated grounding into scoring (validate_score_output, verify_scoring_quotes) and adversary response generation (validate_adversary_output, trigger validation, majority-vote referee).

Reviewed changes

Copilot reviewed 3 out of 3 changed files in this pull request and generated 6 comments.

File Description
backend/app/engines/scoring.py Applies score schema validation + quote grounding to judge output before persisting results.
backend/app/engines/grounding.py New grounding utilities: schema/type guards, quote verification, trigger validation, majority vote, score clamping.
backend/app/engines/adversary.py Adds adversary output schema guard; gates concessions via trigger validation + majority-vote referee.

💡 Add Copilot custom instructions for smarter, more guided reviews. Learn how to get started.

Comment on lines +176 to +179
def validate_adversary_output(out: dict) -> dict:
"""Enforce schema on adversary JSON: required fields, correct types."""
_ensure_str(out, "reply", "[No response generated]")
_ensure_bool(out, "conceded", False)
Comment on lines +188 to +192
def validate_referee_output(out: dict) -> dict:
"""Enforce schema on referee JSON."""
_ensure_bool(out, "earned", False)
_ensure_str(out, "reason", "No reason provided.")
return out
Comment on lines +195 to +200
def validate_score_output(out: dict) -> dict:
"""Enforce schema on scoring JSON and clamp numeric fields."""
if not isinstance(out.get("rubric_results"), list):
out["rubric_results"] = []
if not isinstance(out.get("dimension_scores"), dict):
out["dimension_scores"] = {d: {"score": 0, "max": 0} for d in _DIMENSION_NAMES}
Comment on lines +127 to +130
_DIMENSION_NAMES = {
"Position Defense", "Concession Strategy",
"Anchoring & Offers", "Pressure Resistance", "Legal Reasoning",
}
Comment on lines +64 to +66
if any_fixed:
result["_grounding_corrections"] = True
return result
Comment on lines +204 to +212
gate = grounding.majority_vote(
_referee,
args=(sc, user_msg, claimed, difficulty),
kwargs={},
n=3,
key="earned",
)
gate = grounding.validate_referee_output(gate)
if not gate.get("earned"):
Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment

Labels

None yet

Projects

None yet

Development

Successfully merging this pull request may close these issues.

2 participants