林逍遥 AI林逍遥 AI
登录
RAG引用检索

引用与 RAG:让 Claude 引用原文

·8 分钟阅读

当你让 Claude 基于文档回答问题时,你希望它不仅给出答案,还能指出「这个答案来自哪里」。Citations(引用)功能让 Claude 自动标注回答中每个论点的出处——精确到段落、页码甚至字符位置。这是构建 RAG(检索增强生成)应用的核心能力。

你将学到什么

  • 什么是 RAG,为什么需要引用
  • 如何开启 Citations 功能
  • 不同文档类型的引用格式
  • 构建一个简单的 RAG 问答系统

RAG 简介

RAG(Retrieval-Augmented Generation) 的工作流程:

  1. 检索:从你的知识库中找到与问题相关的文档段落
  2. 增强:把检索到的内容作为上下文传给 Claude
  3. 生成:Claude 基于这些内容回答问题,并标注引用

RAG 解决的核心问题:让 Claude 基于你的私有数据回答,而不是凭自己的训练知识。

开启 Citations

在 messages 内容中使用 document 类型的内容块:

response = client.messages.create(
    model="claude-sonnet-4-6",
    max_tokens=1024,
    messages=[{
        "role": "user",
        "content": [
            {
                "type": "document",
                "source": {
                    "type": "text",
                    "media_type": "text/plain",
                    "data": "公司年假政策:入职满1年享有5天年假,满3年10天,满5年15天。年假必须在当年使用完毕,不可跨年累积。"
                },
                "title": "公司年假政策",
                "citations": {"enabled": True}
            },
            {
                "type": "text",
                "text": "入职 4 年能有几天年假?"
            }
        ]
    }]
)

Claude 的回答会包含引用标记,指向原文的具体位置。

引用在响应中的格式

开启 Citations 后,响应的 content 数组中会包含 cite 类型的块:

for block in response.content:
    if block.type == "text":
        print("回答:", block.text)
    elif block.type == "cite":
        print(f"引用: [{block.cited_text}] (来源: {block.document_title})")

多文档引用

可以同时传入多个文档,Claude 会交叉引用:

messages=[{
    "role": "user",
    "content": [
        {
            "type": "document",
            "source": {"type": "text", "media_type": "text/plain",
                       "data": "产品A: 价格100元,功能:数据分析、报表生成"},
            "title": "产品A说明",
            "citations": {"enabled": True}
        },
        {
            "type": "document",
            "source": {"type": "text", "media_type": "text/plain",
                       "data": "产品B: 价格200元,功能:数据分析、报表生成、AI预测"},
            "title": "产品B说明",
            "citations": {"enabled": True}
        },
        {"type": "text", "text": "两款产品的价格和功能有什么区别?"}
    ]
}]

构建简单的 RAG 系统

一个最小化的 RAG 问答系统:

import anthropic

client = anthropic.Anthropic()

# 你的知识库(实际项目中用向量数据库)
knowledge_base = {
    "退款政策": "用户在购买后7天内可申请全额退款。超过7天不超过30天可申请50%退款。超过30天不予退款。",
    "配送说明": "标准配送3-5个工作日,加急配送1-2个工作日(额外收费20元)。偏远地区加收10元。",
    "会员权益": "普通会员9折,银卡会员85折,金卡会员8折。金卡会员享有专属客服和优先发货。",
}

def answer_with_citations(question: str):
    # 构建文档内容块
    content = []
    for title, text in knowledge_base.items():
        content.append({
            "type": "document",
            "source": {"type": "text", "media_type": "text/plain", "data": text},
            "title": title,
            "citations": {"enabled": True},
        })
    content.append({"type": "text", "text": question})

    response = client.messages.create(
        model="claude-sonnet-4-6",
        max_tokens=1024,
        system="你是客服助手。基于提供的文档回答问题,必须引用原文。如果文档中没有相关信息,说明无法回答。",
        messages=[{"role": "user", "content": content}],
    )

    return response.content

result = answer_with_citations("金卡会员买东西打几折?加急配送多少钱?")
for block in result:
    if hasattr(block, "text"):
        print(block.text, end="")

RAG 的核心挑战

检索质量

RAG 的效果取决于你检索到的文档是否相关。常用方案:

  • 向量搜索:将文档转为向量,用余弦相似度匹配(推荐 OpenAI Embeddings 或 Cohere)
  • 关键词搜索:BM25 算法,适合精确匹配
  • 混合搜索:向量 + 关键词结合

分块策略

长文档需要分割成小段落。常见策略:

  • 按段落分割(保持语义完整)
  • 按固定字数分割(如每 500 字一块)
  • 按章节/标题分割

Tip: 分块太小会丢失上下文,太大会引入噪音。一般 300-800 字一块效果较好。

实战练习

Tip: 用你公司的文档构建一个简单的 RAG。

  1. 准备 3 份文档(FAQ、政策、说明书),用上面的代码让 Claude 回答问题
  2. 检查 Claude 的引用是否准确指向原文
  3. 试着问一个文档中没有的问题,验证 Claude 是否会坦诚告知

关键要点

Note: 本文核心总结

  • Citations 让 Claude 自动标注回答的出处
  • 通过 document 内容块传入文档,设置 citations.enabled = true
  • 支持多文档交叉引用
  • RAG 的核心是检索质量,分块策略很重要

延伸阅读

二维码
微信公众号:lingxiaoyao

关注公众号,获取最新 AI 教程和课程更新

加载评论中...