Detect hallucinations in AI-generated PR descriptions and commit messages.
Uses ChainCheck to decompose text into atomic claims, verify each one, and post a per-claim verdict as a PR comment. Fails the check if the hallucination score exceeds a configurable threshold.
Claim Label Conf Evidence This PR reduces API latency by 40% ⚠️ unsupported0.89no benchmark data provided Adds async batching to the NLI pipeline ✅ supported 0.94— Fixes the rate-limit regression from #142 ⚠️ unsupported0.81issue #142 not referenced ❌ Failing — score
0.71exceeds threshold0.7. Review the flagged claims above before merging.
# .github/workflows/chaincheck.yml
name: ChainCheck
on:
pull_request:
types: [opened, edited, synchronize]
jobs:
hallucination-check:
runs-on: ubuntu-latest
permissions:
pull-requests: write # needed to post the comment
steps:
- uses: pauti04/chaincheck-action@v1.4
env:
GITHUB_TOKEN: ${{ secrets.GITHUB_TOKEN }} # enables diff context
with:
openai-api-key: ${{ secrets.OPENAI_API_KEY }}No
actions/checkoutstep needed — the action fetches the PR diff directly from the GitHub API.
| Input | Required | Default | Description |
|---|---|---|---|
openai-api-key |
✦ | — | OpenAI API key. Required unless anthropic-api-key or ollama-base-url is set. |
anthropic-api-key |
✦ | — | Anthropic API key (alternative to OpenAI). |
ollama-base-url |
✦ | — | Ollama base URL for local inference, e.g. http://localhost:11434. |
model |
auto | Judge model override, e.g. gpt-4o-mini, claude-haiku-4-5-20251001, ollama:llama3. |
|
check |
pr-description |
What to check: pr-description, commit-messages, or any custom string. |
|
threshold |
0.7 |
Fail if hallucination score ≥ this value (0.0–1.0). | |
post-comment |
true |
Post results as a PR comment. | |
methods |
judge |
Detection methods: nli, judge, or nli,judge. |
|
context |
"" |
Optional reference doc to check claims against. |
✦ At least one of openai-api-key, anthropic-api-key, or ollama-base-url is required.
| Output | Description |
|---|---|
score |
Aggregate hallucination score (0.0–1.0) |
risk-level |
low, medium, or high |
Check PR description (default):
- uses: pauti04/chaincheck-action@v1.4
env:
GITHUB_TOKEN: ${{ secrets.GITHUB_TOKEN }}
with:
openai-api-key: ${{ secrets.OPENAI_API_KEY }}
threshold: '0.7'
post-comment: 'true'Check commit messages (requires actions/checkout first):
- uses: actions/checkout@v4 # required for commit-messages mode
with:
fetch-depth: 10
- uses: pauti04/chaincheck-action@v1.4
with:
openai-api-key: ${{ secrets.OPENAI_API_KEY }}
check: commit-messages
threshold: '0.8'NLI + judge ensemble (higher accuracy, slower):
- uses: pauti04/chaincheck-action@v1.4
env:
GITHUB_TOKEN: ${{ secrets.GITHUB_TOKEN }}
with:
openai-api-key: ${{ secrets.OPENAI_API_KEY }}
methods: 'nli,judge'
threshold: '0.65'Use score in downstream steps:
- id: chaincheck
uses: pauti04/chaincheck-action@v1.4
env:
GITHUB_TOKEN: ${{ secrets.GITHUB_TOKEN }}
with:
openai-api-key: ${{ secrets.OPENAI_API_KEY }}
- name: Print score
run: echo "Score=${{ steps.chaincheck.outputs.score }} Risk=${{ steps.chaincheck.outputs.risk-level }}"Use Anthropic Claude instead of OpenAI:
- uses: pauti04/chaincheck-action@v1.4
env:
GITHUB_TOKEN: ${{ secrets.GITHUB_TOKEN }}
with:
anthropic-api-key: ${{ secrets.ANTHROPIC_API_KEY }}
model: 'claude-haiku-4-5-20251001'Use a local Ollama model (self-hosted, no API costs):
- uses: pauti04/chaincheck-action@v1.4
env:
GITHUB_TOKEN: ${{ secrets.GITHUB_TOKEN }}
with:
ollama-base-url: 'http://your-ollama-host:11434'
model: 'ollama:llama3'Soft mode — comment only, never fail:
- uses: pauti04/chaincheck-action@v1.4
env:
GITHUB_TOKEN: ${{ secrets.GITHUB_TOKEN }}
with:
openai-api-key: ${{ secrets.OPENAI_API_KEY }}
threshold: '1.1' # effectively disables failing
post-comment: 'true'- Reads the PR description (or commit messages) from the GitHub event payload
- Fetches the PR diff via the GitHub API and uses it as grounding context for claim verification — no
actions/checkoutrequired - Decomposes text into atomic claims using
gpt-4o-mini - Verifies each claim with the selected method (NLI cross-encoder and/or LLM judge)
- Upserts a single PR comment — edits the previous ChainCheck comment on re-runs instead of posting a new one each push
- Exits non-zero if
aggregate_score ≥ threshold
Powered by ChainCheck — achieves 79% F1 / 94% precision on HaluEval-QA.
Each run makes 1–3 OpenAI API calls (claim decomposition + judge). A typical PR description (200 words) costs ~$0.001 with gpt-4o-mini.
MIT