Applied AI School
v0 · 規劃中
Anthropic

Citations

讓 Claude 把答案的「每句話來自原文哪段」結構化標註出來——比叫 model 「請引用」可靠,是 API 層級保證的格式。

TL;DR

  • citations: {enabled: true} 加在 document block 裡,response 的 text block 會自帶 citations 陣列
  • 每筆 citation 包 cited_text(原文片段)+ start_page_number / end_page_number(PDF)或 char index(純文字)
  • 比 prompt 寫「請引用頁碼」可靠很多——API 層級保證格式,不會幻覺出不存在的頁碼

一個情境:法務 AI 助手要敢被質疑

你做了一個合約 QA 工具:user 上傳合約 PDF,問「違約金條款是什麼?」Claude 回「違約金為合約金額的 20%」。

法務看到只會回你一句話:「根據哪一條?哪一頁?字面怎麼寫?」 沒辦法說清楚的話,整個工具沒人敢用——做合約決策不能靠 LLM 一句話。

Citations 就是這個問題的官方答案。response 不只是文字,每段陳述都附 source location:哪份文件、哪幾頁、原文哪一段支持這個說法。

怎麼開

document block 多加兩個欄位:title(顯示用名稱)+ citations: {enabled: true}

import base64

with open("contract.pdf", "rb") as f:
    pdf_b64 = base64.standard_b64encode(f.read()).decode("utf-8")

messages = [{
    "role": "user",
    "content": [
        {
            "type": "document",
            "source": {
                "type": "base64",
                "media_type": "application/pdf",
                "data": pdf_b64,
            },
            "title": "供應合約-2026.pdf",       # ← 顯示用
            "citations": {"enabled": True},   # ← 開關
        },
        {"type": "text", "text": "違約金條款是什麼?依據哪一條?"},
    ],
}]

Response 結構:text block 多一個 citations 欄位

開了 citations 之後 res.content 結構變了。text block 不再是單純的字串,而是句子被切片、每片帶 citation

[
    {"type": "text",
     "text": "根據合約第 12 條,違約金為合約總金額的 20%。",
     "citations": [
        {
            "type": "page_location",
            "cited_text": "若任一方未能履行本合約義務,違約方應支付合約總金額之 20% 作為違約金⋯⋯",
            "document_index": 0,
            "document_title": "供應合約-2026.pdf",
            "start_page_number": 4,
            "end_page_number": 4,
        }
     ]},
    {"type": "text",
     "text": "另須於 30 日內補正⋯⋯",
     "citations": [...]
    },
]

關鍵欄位:

欄位意思
cited_text原文「字面字串」——逐字從你的文件來
document_index第幾份文件(多份的時候 0、1、2⋯)
document_title你給的 title
start_page_number / end_page_numberPDF 頁碼範圍

純文字 source 改用 char_location,給 start_char_index / end_char_index 而不是頁碼。

純文字也能 cite

不一定要 PDF——把段落塞進 document block 即可:

{
    "type": "document",
    "source": {
        "type": "text",
        "media_type": "text/plain",
        "data": article_text,
    },
    "title": "earth_article",
    "citations": {"enabled": True},
}

回的 citation 變成 citation_char_location,告訴你 cited_text 在原文的字元 index——拿來在 UI highlight 那段文字超直接。

為什麼比 prompt 寫「請引用」可靠

直覺寫法:

請依據文件回答,並在每段後面附上頁碼,例如「(p.4)」。

問題:

  • 頁碼有時候是幻覺——model 會自己編一個聽起來合理的頁碼
  • 格式不穩——時而「(p.4)」、時而「第 4 頁」、時而忘了寫
  • 拆不開答案跟引用——要 regex parse 才知道哪句對哪段

Citations API 是 server-side enforcecited_text 必定是文件裡真的存在的字串,頁碼必定對應實際的頁碼。不需要解析、不會幻覺、結構穩定

prompt 寫「請引用」    →  字串裡塞 (p.4),要正則解,可能幻覺
citations API        →  結構化 JSON,server 保證 cited_text 來自原文

UI 怎麼接

兩種常見呈現——句子尾巴掛角標 hover 看 cited_text,或左右雙欄(左答案、右原文 highlight)。後者對長 PDF 特別有用,user 直接看到原始合約哪一段被 cite。

跟 RAG 一起用

RAG 那章 講過:embedding 把文件切片、retrieve 相關幾段、塞進 prompt 給 Claude。Citations 正好補上 RAG 缺的最後一塊:不只 retrieve 對的段,還能讓 user 驗證 model 真的有用那段。

[檢索 top-k 段]  →  [塞進 document block 並 enable citations]
                                  ↓
            [Claude 答案 + cited_text 對到 retrieved 段]
                                  ↓
                  [UI 顯示原文片段,用戶可點開 source]

很多 production RAG 系統會把 citations 跟 retrieved chunks 對映回原始文件位置(page、URL、段落 anchor),做出**「答案 → 引文 → 原始來源」**的完整 trace。

多份文件一起 cite

messages 裡可以塞多個 document block,每個給一個 title——Claude 自動追蹤是哪份的哪頁:

content = [
    {"type": "document", "source": {...}, "title": "合約 A", "citations": {"enabled": True}},
    {"type": "document", "source": {...}, "title": "合約 B", "citations": {"enabled": True}},
    {"type": "document", "source": {...}, "title": "公司政策", "citations": {"enabled": True}},
    {"type": "text", "text": "比較三份文件的違約金條款。"},
]

response 的 citation 用 document_index(0、1、2)+ document_title 標明出處。

什麼時候開、什麼時候不開

情境開?
法務 / 醫療 / 金融文件 QA必開——一定要可驗證
RAG-based 客服系統開——user 看了更信
一般聊天、創意寫作不必——沒有「source」這個概念
純摘要任務看情況——要可追溯就開

計費

Citations 本身不另外收費,但 model 會被引導「多生 quote 字串」,所以 output token 通常會比沒開時多一點。實測差異不大、可忽略;真要省可以在 prompt 寫「精簡引用」。

接下來

下一篇看 Section 6 最後兩個 server-side 能力:code execution + Files API——讓 Claude 在 Anthropic 的 Python sandbox 裡跑 code、產生圖表,然後用 Files API 在 multi-turn 裡共享檔案。