You signed in with another tab or window. Reload to refresh your session.You signed out in another tab or window. Reload to refresh your session.You switched accounts on another tab or window. Reload to refresh your session.Dismiss alert
The assistant answers every question with the same confident tone whether it is repeating Surah al-Fatiha or inventing a hadith number on the spot. There is no mechanism to notice when the model is guessing. This issue adds inference-time hallucination detection via self-consistency: for high-stakes questions, sample the model more than once (and/or re-ask it to verify its own factual claims), measure agreement across samples, and treat disagreement as a hallucination signal — so a shaky answer can be softened, flagged for verification, or abstained on instead of served as fact. This is a general fabrication guard that complements the citation-vs-corpus check (#40) and the offline eval harness (#16): #40 catches wrong Quran text, #16 measures quality in the lab; this catches the model making things up at request time, before the user sees it.
Current state
/chat calls chat.send_message exactly once (main.py, lines 143–151) at temperature: 0.7 and returns response.text verbatim (lines 176–179). A single stochastic sample is trusted completely — there is no second look, no agreement check, nothing between the model's first guess and the user.
The only guardrails are Gemini's built-in safety settings (get_safety_settings, lines 91–109), which police harm categories, not factual accuracy.
ISLAMIC_CONTEXT (lines 57–71) says "Acknowledge when a question is beyond your scope," but nothing measures whether the model actually knows the answer — so it rarely does.
No structured claim extraction exists; the response is an opaque blob of text.
What to build
A self-consistency sampler — for questions routed as high-stakes (factual/ruling/citation-bearing; reuse intent signals from [Enhancement] Question-understanding pipeline: intent classification, clarifying questions, answer-length calibration, and suggested follow-ups #42 or a cheap heuristic, and skip sampling for greetings/small-talk to protect latency and cost), draw N samples (or one answer plus a verification pass) and compare their key factual claims — citations, numbers, names, rulings. Make N and the trigger policy configurable, and justify the latency/cost tradeoff in the PR.
A claim-agreement scorer — extract the load-bearing claims from each sample (a structured-output Gemini call is acceptable) and compute an agreement score: do the samples cite the same verses, the same collections, the same conclusion? Divergence on citations/numbers is a strong hallucination signal.
A response policy — below an agreement threshold, either abstain ("I'm not certain enough to answer this reliably; please consult a scholar / a cited source"), hedge with an explicit uncertainty note, or strip the unsupported claim. Never silently serve a low-agreement answer as confident fact. Emit a machine-readable signal (see #ai-19's confidence work — coordinate so they share one score, not two competing ones).
Metadata — an optional consistency: {samples, agreement_score, action_taken} block on ChatResponse, additive and optional.
Tests — offline tests with a mocked client that returns deliberately divergent samples, asserting the scorer flags them and the policy abstains/hedges; and convergent samples pass through unchanged. No live API calls in CI.
Acceptance criteria
High-stakes questions trigger multi-sample (or answer-plus-verification) generation; low-stakes chat keeps a single fast path — trigger policy is configurable and documented.
Load-bearing claims (citations, numbers, names, conclusions) are extracted and compared across samples to produce an agreement score.
Below the agreement threshold the service abstains, hedges, or strips the unsupported claim — never serves it as confident fact.
Sampling runs concurrently and reuses caching so the added latency is bounded and measured (report the numbers in the PR).
The confidence/agreement signal is shared with the confidence-scoring work (#ai-19), not duplicated.
ChatResponse carries the optional consistency block; existing clients are unaffected.
Tests with mocked divergent and convergent samples pass offline; CI stays green.
Pointers
main.py — the single send_message call and generation config (lines 143–151), response.text return (lines 153–179), get_safety_settings (lines 91–109), ISLAMIC_CONTEXT (lines 57–71).
CI (.github/workflows/ci.yml) has no pytest step — add one and extend flake8 to new modules.
PRs target the dev branch (see CONTRIBUTING.md).
Difficulty
High — self-consistency and claim-level agreement scoring are subtle to get right (paraphrase-tolerant claim matching, threshold tuning, avoiding both over- and under-abstention), and doing it without wrecking latency requires careful concurrency and caching on top of the async fix. This is real ML-systems work, not a wrapper.
🏆 GrantFox OSS — Official Campaign | FWC26. Apply for this issue through the GrantFox campaign page. The maintainer assigns one contributor before work starts; unassigned PRs may not be reviewed. PRs target the dev branch. Quality bar: CI must stay green.
💬 Questions or need help? Reach the maintainers and other contributors on the DeenBridge Telegram: https://t.me/+nst9lXNj1wc4ZDE0
Summary
The assistant answers every question with the same confident tone whether it is repeating Surah al-Fatiha or inventing a hadith number on the spot. There is no mechanism to notice when the model is guessing. This issue adds inference-time hallucination detection via self-consistency: for high-stakes questions, sample the model more than once (and/or re-ask it to verify its own factual claims), measure agreement across samples, and treat disagreement as a hallucination signal — so a shaky answer can be softened, flagged for verification, or abstained on instead of served as fact. This is a general fabrication guard that complements the citation-vs-corpus check (#40) and the offline eval harness (#16): #40 catches wrong Quran text, #16 measures quality in the lab; this catches the model making things up at request time, before the user sees it.
Current state
/chatcallschat.send_messageexactly once (main.py, lines 143–151) attemperature: 0.7and returnsresponse.textverbatim (lines 176–179). A single stochastic sample is trusted completely — there is no second look, no agreement check, nothing between the model's first guess and the user.get_safety_settings, lines 91–109), which police harm categories, not factual accuracy.ISLAMIC_CONTEXT(lines 57–71) says "Acknowledge when a question is beyond your scope," but nothing measures whether the model actually knows the answer — so it rarely does.What to build
send_messageblocks the event loop — build on the async fix, don't fight it), cache verification results with [Enhancement] Semantic response cache with embedding-similarity matching for repeated questions #27's cache, and keep single-sample fast paths for low-stakes chat.consistency: {samples, agreement_score, action_taken}block onChatResponse, additive and optional.Acceptance criteria
ChatResponsecarries the optionalconsistencyblock; existing clients are unaffected.Pointers
main.py— the singlesend_messagecall and generation config (lines 143–151),response.textreturn (lines 153–179),get_safety_settings(lines 91–109),ISLAMIC_CONTEXT(lines 57–71)..github/workflows/ci.yml) has no pytest step — add one and extend flake8 to new modules.devbranch (seeCONTRIBUTING.md).Difficulty
High — self-consistency and claim-level agreement scoring are subtle to get right (paraphrase-tolerant claim matching, threshold tuning, avoiding both over- and under-abstention), and doing it without wrecking latency requires careful concurrency and caching on top of the async fix. This is real ML-systems work, not a wrapper.
🏆 GrantFox OSS — Official Campaign | FWC26. Apply for this issue through the GrantFox campaign page. The maintainer assigns one contributor before work starts; unassigned PRs may not be reviewed. PRs target the
devbranch. Quality bar: CI must stay green.💬 Questions or need help? Reach the maintainers and other contributors on the DeenBridge Telegram: https://t.me/+nst9lXNj1wc4ZDE0