跳到主要内容

生成策略与引用溯源

问题

RAG 中如何设计 Prompt 模板?如何实现引用溯源?

答案

检索到相关文档后,如何将其与用户问题组织成 Prompt 送入 LLM,以及如何让回答包含可追溯的引用,是 RAG 生成阶段的核心。

一、Prompt 模板设计

基础模板

RAG_PROMPT = """基于以下参考资料回答用户问题。
如果参考资料中没有相关信息,请明确说明"根据现有资料无法回答",不要编造。

参考资料:
{context}

用户问题:{question}

请用中文回答:"""

带引用的模板

RAG_PROMPT_WITH_CITATION = """基于以下编号的参考资料回答用户问题。
回答中必须用 [1]、[2] 等标注引用了哪条资料。
如果参考资料不足以回答,明确说明。

参考资料:
[1] {doc_1}
[2] {doc_2}
[3] {doc_3}

用户问题:{question}

请用中文回答,并标注引用来源:"""

二、引用溯源实现

1. 文档级引用

def generate_with_citations(query: str, docs: list, llm):
# 为每个文档编号
context_parts = []
for i, doc in enumerate(docs, 1):
source = doc.metadata.get("source", "未知来源")
page = doc.metadata.get("page", "")
context_parts.append(f"[{i}] (来源: {source}, 第{page}页)\n{doc.page_content}")

context = "\n\n".join(context_parts)

response = llm.invoke(RAG_PROMPT_WITH_CITATION.format(
context=context,
question=query,
doc_1=context_parts[0] if len(context_parts) > 0 else "",
doc_2=context_parts[1] if len(context_parts) > 1 else "",
doc_3=context_parts[2] if len(context_parts) > 2 else "",
))

return {
"answer": response.content,
"sources": [
{"index": i+1, "source": doc.metadata.get("source"), "page": doc.metadata.get("page")}
for i, doc in enumerate(docs)
]
}

2. 句子级引用(精确到段落)

更精细的引用方式,让 LLM 标注每个论述的具体来源:

# 输出示例
MVCC 通过为每条记录维护多个版本来实现并发控制 [1]。
在 Read Committed 隔离级别下,每次查询都会创建新的 Read View [2]。
而在 Repeatable Read 级别下,整个事务共享一个 Read View [1][2]

三、上下文管理策略

Stuff(填充)

将所有检索到的文档直接塞入 Prompt:

简单直接,适合文档量小、Context Window 足够的场景

Map-Reduce

  • 先对每个文档独立总结,再合并
  • 适合大量文档,但多次 LLM 调用成本高

Refine(逐步精炼)

  • 逐个文档迭代优化答案
  • 答案质量高,但串行执行慢
策略适用场景优点缺点
Stuff文档少,窗口够简单快速文档多会超窗口
Map-Reduce大量文档可并行多次 LLM 调用
Refine需要高质量综合答案质量高串行慢

四、减少幻觉的技巧

技巧实现方式
明确约束"仅基于参考资料回答,如无法回答请说明"
要求引用"每个论述必须标注来源编号"
低 Temperaturetemperature=0 减少创造性
分离检索和判断先让 LLM 判断"是否能回答",再生成答案
Faithful 验证用第二个 LLM 验证答案是否忠于原文

常见面试问题

Q1: RAG 中 LLM 的 temperature 应该设多少?

答案

  • 知识库问答temperature=0,追求确定性和准确性
  • 创意写作辅助temperature=0.7,允许一定创造性
  • 代码生成temperature=0,代码必须精确

Q2: 如何处理检索到的文档相互矛盾?

答案

  1. 时间优先:在 Prompt 中指示"优先参考最新的资料"
  2. 来源权重:官方文档 > 社区文档 > 用户评论
  3. 显式说明:让 LLM 在回答中指出"资料存在矛盾,分别说明"

相关链接