Skip to content

Add example: check citation faithfulness in RAG#1296

Open
Palo-Alto-AI-Research-Lab wants to merge 1 commit into
google-gemini:mainfrom
Palo-Alto-AI-Research-Lab:feat/citation-faithfulness-check
Open

Add example: check citation faithfulness in RAG#1296
Palo-Alto-AI-Research-Lab wants to merge 1 commit into
google-gemini:mainfrom
Palo-Alto-AI-Research-Lab:feat/citation-faithfulness-check

Conversation

@Palo-Alto-AI-Research-Lab

Copy link
Copy Markdown

When a Gemini RAG answer cites its sources, the citations fail in ways that read as authoritative and slip past an LLM judge: fabricated (a quote in no document), frankenquote (real words, a sentence never written contiguously), and misattributed (a real quote from the wrong document).

This example shows a cheap deterministic detector → expensive judge pattern:

  1. Ask Gemini, via structured output (a response_schema), to return each claim with the document_id it relies on and a short verbatim quote.
  2. Run a 0-token verbatim gate (pure Python — no model, no key) that checks each quote appears in the cited document. This rejects the three failure modes above and runs offline.
  3. Only for quotes that pass the gate, optionally call a burden-of-proof judge — fabrications never reach it, so they cost zero tokens.

The offline section executes end-to-end (verified with nbclient):

OK   [        found]  Gemini 2.5 Pro supports a 1M token context.
FLAG [misattributed]  Flash is built for low latency.
FLAG [    not_found]  Flash has a 1 million token context.
FLAG [    not_found]  Gemini 2.5 Pro runs fully offline.

Added to examples/README.md. The live section uses the google-genai SDK with a response_schema. The gate is inlined so the notebook has no extra dependency; its standalone, framework-agnostic version (gate + burden-of-proof judge) lives at https://github.com/Palo-Alto-AI-Research-Lab/verbatim-citation-gate .

Deterministically verify Gemini RAG citations are faithful to their sources: a
zero-token verbatim gate that catches fabricated, franken-, and misattributed
quotes before they reach a user, plus an optional burden-of-proof judge for the
ambiguous case. Offline section runs with no API key; live section uses the
google-genai SDK with a response_schema, gated behind GOOGLE_API_KEY.

Co-Authored-By: Claude Fable 5 <noreply@anthropic.com>
@review-notebook-app

Copy link
Copy Markdown

Check out this pull request on  ReviewNB

See visual diffs & provide feedback on Jupyter Notebooks.


Powered by ReviewNB

@gemini-code-assist

Copy link
Copy Markdown
Contributor

Summary of Changes

Hello, I'm Gemini Code Assist1! I'm currently reviewing this pull request and will post my feedback shortly. In the meantime, here's a summary to help you and other reviewers quickly get up to speed!

This pull request introduces a new example notebook focused on improving the reliability of RAG systems by verifying citation faithfulness. It provides a lightweight, deterministic approach to filter out common citation errors like fabrications and misattributions, reducing unnecessary LLM costs by only invoking a judge for potentially valid citations.

Highlights

  • New RAG Citation Example: Added a new notebook, Citation_Faithfulness_Check.ipynb, demonstrating how to detect fabricated, frankenquoted, or misattributed citations in RAG pipelines.
  • Deterministic Verification Pattern: Introduced a 'cheap deterministic detector → expensive judge' pattern using a zero-token verbatim gate to filter citations before optional LLM-based evaluation.
  • Documentation Update: Updated examples/README.md to include the new citation faithfulness check example.
Using Gemini Code Assist

The full guide for Gemini Code Assist can be found on our documentation page, here are some quick tips.

Invoking Gemini

You can request assistance from Gemini at any point by creating a comment using either /gemini <command> or @gemini-code-assist <command>. Below is a summary of the supported commands on the current page.

Feature Command Description
Code Review /gemini review Performs a code review for the current pull request in its current state.
Pull Request Summary /gemini summary Provides a summary of the current pull request in its current state.
Comment @gemini-code-assist Responds in comments when explicitly tagged, both in pull request comments and review comments.
Help /gemini help Displays a list of available commands.

Customization

To customize the Gemini Code Assist for GitHub experience, repository maintainers can create a configuration file and/or provide a custom code review style guide (such as PEP-8 for Python) by creating and adding files to a .gemini/ folder in the base of the repository. Detailed instructions can be found here.

Limitations & Feedback

Gemini Code Assist may make mistakes. Please leave feedback on any instances where its feedback is incorrect or counterproductive. You can react with 👍 and 👎 on @gemini-code-assist comments. If you're interested in giving your feedback about your experience with Gemini Code Assist for GitHub and other Google products, sign up here.

Footnotes

  1. Review the Privacy Notices, Generative AI Prohibited Use Policy, Terms of Service, and learn how to configure Gemini Code Assist in GitHub here. Gemini can make mistakes, so double check it and use code with caution.

@github-actions github-actions Bot added status:awaiting review PR awaiting review from a maintainer component:examples Issues/PR referencing examples folder labels Jul 24, 2026
@google-cla

google-cla Bot commented Jul 24, 2026

Copy link
Copy Markdown

Thanks for your pull request! It looks like this may be your first contribution to a Google open source project. Before we can look at your pull request, you'll need to sign a Contributor License Agreement (CLA).

View this failed invocation of the CLA check for more information.

For the most up to date status, view the checks section at the bottom of the pull request.

@gemini-code-assist gemini-code-assist Bot left a comment

Copy link
Copy Markdown
Contributor

Choose a reason for hiding this comment

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

Code Review

This pull request introduces a new notebook, Citation_Faithfulness_Check.ipynb, which demonstrates a deterministic verbatim gate and an optional burden-of-proof judge to verify RAG citation faithfulness, and registers it in the examples README. Feedback on the notebook includes aligning it with the repository style guide by adopting the modern Interactions API (client.interactions.create) instead of the legacy generate_content method, using GEMINI_API_KEY instead of GOOGLE_API_KEY, implementing a Colab parameter selector for model selection, using %pip for package installation, and adding an 'Open in Colab' button directly below the main header.

Comment on lines +145 to +180
"import os\n",
"\n",
"if not os.getenv(\"GOOGLE_API_KEY\"):\n",
" print(\"Set GOOGLE_API_KEY to run the live example.\")\n",
"else:\n",
" from google import genai\n",
" from pydantic import BaseModel\n",
"\n",
" class Citation(BaseModel):\n",
" claim: str\n",
" document_id: str\n",
" quote: str\n",
"\n",
" class CitedAnswer(BaseModel):\n",
" answer: str\n",
" citations: list[Citation]\n",
"\n",
" client = genai.Client()\n",
" library = \"\\n\".join(f\"[{doc_id}] {text}\" for doc_id, text in DOCS.items())\n",
" prompt = (\n",
" \"Answer using only the library. For each claim, cite the document_id and a short quote \"\n",
" f\"copied verbatim from that document.\\n\\nLibrary:\\n{library}\\n\\n\"\n",
" \"Question: What context window does Gemini 2.5 Pro have, and what is Flash optimized for?\"\n",
" )\n",
" resp = client.models.generate_content(\n",
" model=\"gemini-2.5-flash\",\n",
" contents=prompt,\n",
" config={\"response_mime_type\": \"application/json\", \"response_schema\": CitedAnswer},\n",
" )\n",
" cited: CitedAnswer = resp.parsed\n",
" print(cited.answer, \"\\n\")\n",
" for c in cited.citations:\n",
" status = gate(c.quote, c.document_id, DOCS)\n",
" flag = \"OK \" if status == \"found\" else \"FLAG\"\n",
" print(f\"{flag} [{status:>13}] {c.quote!r} -> {c.document_id}\")"
]

Copy link
Copy Markdown
Contributor

Choose a reason for hiding this comment

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

high

This code block contains several style guide violations and outdated patterns:

  1. It uses # pip install instead of %pip install with the correct SDK version.
  2. It uses the legacy GOOGLE_API_KEY instead of GEMINI_API_KEY.
  3. It hardcodes the model name instead of using a Colab parameter selector.
  4. It uses the legacy client.models.generate_content instead of the modern client.interactions.create API.

Updating this block to use the modern Interactions API and correct environment variables will align it with the repository standards.

    "%pip install -U -q 'google-genai>=2.9.0' pydantic\n",
    "import os\n",
    "\n",
    "MODEL_ID = \"gemini-2.5-flash\"  # @param [\"gemini-2.5-flash\", \"gemini-2.5-pro\"]\n",
    "\n",
    "if not os.getenv(\"GEMINI_API_KEY\"):\n",
    "    print(\"Set GEMINI_API_KEY to run the live example.\")\n",
    "else:\n",
    "    import json\n",
    "    from google import genai\n",
    "    from pydantic import BaseModel\n",
    "\n",
    "    class Citation(BaseModel):\n",
    "        claim: str\n",
    "        document_id: str\n",
    "        quote: str\n",
    "\n",
    "    class CitedAnswer(BaseModel):\n",
    "        answer: str\n",
    "        citations: list[Citation]\n",
    "\n",
    "    client = genai.Client()\n",
    "    library = \"\\n\".join(f\"[{doc_id}] {text}\" for doc_id, text in DOCS.items())\n",
    "    prompt = (\n",
    "        \"Answer using only the library. For each claim, cite the document_id and a short quote \"\n",
    "        f\"copied verbatim from that document.\\n\\nLibrary:\\n{library}\\n\\n\"\n",
    "        \"Question: What context window does Gemini 2.5 Pro have, and what is Flash optimized for?\"\n",
    "    )\n",
    "    interaction = client.interactions.create(\n",
    "        model=MODEL_ID,\n",
    "        input=prompt,\n",
    "        config={\"response_mime_type\": \"application/json\", \"response_schema\": CitedAnswer},\n",
    "    )\n",
    "    response_text = interaction.steps[-1].content[0].text\n",
    "    cited = CitedAnswer.model_validate_json(response_text)\n",
    "    print(cited.answer, \"\\n\")\n",
    "    for c in cited.citations:\n",
    "        status = gate(c.quote, c.document_id, DOCS)\n",
    "        flag = \"OK  \" if status == \"found\" else \"FLAG\"\n",
    "        print(f\"{flag} [{status:>13}]  {c.quote!r} -> {c.document_id}\")"
References
  1. All new quickstart notebooks must use the Interactions API (client.interactions.create()) instead of the legacy client.models.generate_content(). (link)
  2. The API key should always be gathered from the GEMINI_API_KEY colab secret. If the code is using the legacy GOOGLE_API_KEY secret, ask them to update it. (link)
  3. When selecting a model, use a colab selector for easier maintainability. (link)
  4. When using the google-genai SDK's Interactions API, InteractionStep objects in result.steps use step.content rather than the older step.model_output.parts structure.

Comment on lines +8 to +9
"# Check citation faithfulness in RAG\n",
"\n",

Copy link
Copy Markdown
Contributor

Choose a reason for hiding this comment

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

medium

According to the repository style guide, you should include the "open in colab" button immediately after the H1 header.

Suggested change
"# Check citation faithfulness in RAG\n",
"\n",
"# Check citation faithfulness in RAG\n",
"\n",
"<a target=\"_blank\" href=\"https://colab.research.google.com/github/google-gemini/cookbook/blob/main/examples/Citation_Faithfulness_Check.ipynb\"><img src=\"https://colab.research.google.com/assets/colab-badge.svg\" height=30/></a>\n",
"\n"
References
  1. Include the "open in colab" button immediately after the H1. It should look like where URL should be https://colab.research.google.com/github/google-gemini/cookbook/blob/main/ followed by the notebook location in the cookbook (link)

Comment on lines +133 to +134
"the same gate over them. Uses the `google-genai` SDK with a `response_schema`; needs\n",
"`GOOGLE_API_KEY` (not run in CI)."

Copy link
Copy Markdown
Contributor

Choose a reason for hiding this comment

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

medium

According to the repository style guide, the API key should always be gathered from the GEMINI_API_KEY colab secret. Please update the reference to GOOGLE_API_KEY in this markdown cell.

Suggested change
"the same gate over them. Uses the `google-genai` SDK with a `response_schema`; needs\n",
"`GOOGLE_API_KEY` (not run in CI)."
"the same gate over them. Uses the `google-genai` SDK with a `response_schema`; needs\n",
"`GEMINI_API_KEY` (not run in CI)."
References
  1. The API key should always be gathered from the GEMINI_API_KEY colab secret. If the code is using the legacy GOOGLE_API_KEY secret, ask them to update it. (link)

@kkorpal kkorpal self-assigned this Jul 24, 2026
Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment

Labels

component:examples Issues/PR referencing examples folder status:awaiting review PR awaiting review from a maintainer

Projects

None yet

Development

Successfully merging this pull request may close these issues.

3 participants