RAG引用检索
引用与 RAG:让 Claude 引用原文
·约 8 分钟阅读
当你让 Claude 基于文档回答问题时,你希望它不仅给出答案,还能指出「这个答案来自哪里」。Citations(引用)功能让 Claude 自动标注回答中每个论点的出处——精确到段落、页码甚至字符位置。这是构建 RAG(检索增强生成)应用的核心能力。
你将学到什么
- 什么是 RAG,为什么需要引用
- 如何开启 Citations 功能
- 不同文档类型的引用格式
- 构建一个简单的 RAG 问答系统
RAG 简介
RAG(Retrieval-Augmented Generation) 的工作流程:
- 检索:从你的知识库中找到与问题相关的文档段落
- 增强:把检索到的内容作为上下文传给 Claude
- 生成: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。
- 准备 3 份文档(FAQ、政策、说明书),用上面的代码让 Claude 回答问题
- 检查 Claude 的引用是否准确指向原文
- 试着问一个文档中没有的问题,验证 Claude 是否会坦诚告知
关键要点
Note: 本文核心总结
- Citations 让 Claude 自动标注回答的出处
- 通过 document 内容块传入文档,设置 citations.enabled = true
- 支持多文档交叉引用
- RAG 的核心是检索质量,分块策略很重要