Add example: check citation faithfulness in RAG#1296
Add example: check citation faithfulness in RAG#1296Palo-Alto-AI-Research-Lab wants to merge 1 commit into
Conversation
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>
|
Check out this pull request on See visual diffs & provide feedback on Jupyter Notebooks. Powered by ReviewNB |
Summary of ChangesHello, 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
Using Gemini Code AssistThe 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
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 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
|
|
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. |
There was a problem hiding this comment.
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.
| "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}\")" | ||
| ] |
There was a problem hiding this comment.
This code block contains several style guide violations and outdated patterns:
- It uses
# pip installinstead of%pip installwith the correct SDK version. - It uses the legacy
GOOGLE_API_KEYinstead ofGEMINI_API_KEY. - It hardcodes the model name instead of using a Colab parameter selector.
- It uses the legacy
client.models.generate_contentinstead of the modernclient.interactions.createAPI.
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
- All new quickstart notebooks must use the Interactions API (client.interactions.create()) instead of the legacy client.models.generate_content(). (link)
- 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)
- When selecting a model, use a colab selector for easier maintainability. (link)
- 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.
| "# Check citation faithfulness in RAG\n", | ||
| "\n", |
There was a problem hiding this comment.
According to the repository style guide, you should include the "open in colab" button immediately after the H1 header.
| "# 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
- 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)
| "the same gate over them. Uses the `google-genai` SDK with a `response_schema`; needs\n", | ||
| "`GOOGLE_API_KEY` (not run in CI)." |
There was a problem hiding this comment.
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.
| "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
- 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)
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:
response_schema), to return each claim with thedocument_idit relies on and a short verbatim quote.The offline section executes end-to-end (verified with
nbclient):Added to
examples/README.md. The live section uses thegoogle-genaiSDK with aresponse_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 .