Skip to content

feat(rag): native Anthropic Citations API (opt-in)#11

Merged
silversurfer562 merged 1 commit into
mainfrom
feat/native-citations
May 8, 2026
Merged

feat(rag): native Anthropic Citations API (opt-in)#11
silversurfer562 merged 1 commit into
mainfrom
feat/native-citations

Conversation

@silversurfer562
Copy link
Copy Markdown
Member

Summary

Adds opt-in native Anthropic Citations API support to attune-rag, sequenced as item (2) from the 2026-05-08 enhancements briefing.

  • New code path: use_native_citations=True on RagPipeline.run_and_generate sends retrieved hits as custom_content document blocks; the model emits claim-level citations attached to its response text. Returns claim-level attribution with character precision.
  • Legacy [P{n}] path is preserved unchanged — it has a 2026-04-19 A/B-validated hallucination win that we don't throw away. New path is purely additive, default off, until benchmark validates.
  • Two parallel paths, four-row behavior matrix, Gemini auto-falls-back, all wired and tested.

Spec: specs/rag-native-citations/{requirements,design,tasks}.md.

What landed

  • attune_rag.ClaimCitation — claim-level attribution dataclass
  • attune_rag.format_claim_citations_markdown — footnote-style renderer
  • LLMProvider.supports_native_citations + generate_with_citations (default NotImplementedError)
  • ClaudeProvider.generate_with_citations (verified against SDK 0.96.0 — CitationContentBlockLocation field names)
  • RagResult.claim_citations + used_native_citations (additive; defaults preserve all existing callers)
  • attune-rag query --native-citations CLI flag
  • attune-rag-benchmark --native-citations side-by-side column (mean faithfulness, refusal rate, hallucination rate, citation emit rate, p95 latency)
  • docs/rag/native-citations.md design note

Tests

  • +24 new unit tests, all passing:
    • 8 for ClaimCitation dataclass + re-export
    • 10 for format_claim_citations_markdown (footnote rendering, base_url, marker order, deduped footnote numbers, empty-citations note)
    • 16 for ClaudeProvider.generate_with_citations (recorded fixture parser + payload shape; MAX_CITATION_DOCUMENTS boundary; defensive parsing for missing fields)
    • 8 for pipeline (full four-row behavior matrix, retrieval parity test, full-content-not-truncated guard)
  • Full suite: 348 passed, 3 xpassed.
  • Retrieval P@1: 95% (well above 73% workspace floor; retrieval untouched).
  • Ruff: clean on touched files.

⚠️ Verification gates deferred (V2, V3) — needs live API spend

These are documented in docs/rag/native-citations.md and were intentionally not run autonomously because they require Anthropic API credits:

  • V2 — cache_control on document blocks: empirically confirm a 2-call test yields cache hits when documents are identical. Currently cache_control is off on the native path; if V2 confirms parity with text-block caching, attach cache_control: ephemeral to the first document.
  • V3 — document-count ceiling: hardcoded MAX_CITATION_DOCUMENTS = 20 in ClaudeProvider. Re-verify against current API limits and adjust if needed.

Both gates affect optional polish, not correctness. Native citations works end-to-end as committed; v2 just leaves performance on the table until verified.

Test plan

  • CI green on all matrix rows (Linux/macOS/Windows × Python 3.10–3.13)
  • (Optional, on user) Run attune-rag-benchmark --with-faithfulness --native-citations on a real corpus to populate the side-by-side table
  • (Optional, on user) Resolve V2/V3 verification gates and update doc

🤖 Generated with Claude Code

New opt-in `use_native_citations=True` kwarg on
RagPipeline.run_and_generate sends retrieved hits as Anthropic
custom_content document blocks and parses claim-level citations
back into a new ClaimCitation type. The legacy [P{n}]-marker
path is preserved unchanged (it has a 2026-04-19 A/B-validated
hallucination win), so this is purely additive.

Surface added:
- attune_rag.ClaimCitation (response_span, document_index,
  document_title, cited_text, cited_block_index)
- attune_rag.format_claim_citations_markdown — footnote-style
  rendering of response text + citations
- attune_rag.providers.base.{CitationDocument, CitedResponse}
- LLMProvider.supports_native_citations flag +
  generate_with_citations method (default NotImplementedError)
- ClaudeProvider implements both; GeminiProvider declares the
  flag = False, pipeline detects this and falls back

Surface modified (additive only):
- RagResult gains claim_citations and used_native_citations,
  both default empty/False so existing callers are unaffected
- attune-rag query --native-citations CLI flag
- attune-rag-benchmark --native-citations side-by-side column

Verification gates V2 (cache_control on document blocks) and V3
(document-count ceiling) are deferred — they require live API
spend. Conservative defaults: cache_control OFF on the new path
in v1, MAX_CITATION_DOCUMENTS=20 hardcoded with a clean
ValueError. Both flagged in docs/rag/native-citations.md.

Tests: +24 unit tests (8 ClaimCitation, 10 format_claim_citations
helper, 16 ClaudeProvider citations parser+payload, 8 pipeline
behavior matrix + parity). Full suite 348 passed. Retrieval P@1
unchanged at 95% (well above 73% workspace floor).

Spec: specs/rag-native-citations/{requirements,design,tasks}.md

Co-Authored-By: Claude Opus 4.7 <noreply@anthropic.com>
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.

1 participant