RAG 检索结果附带来源片段的组装方案
RAG 的检索结果不要直接拼成一段无标识的 prompt。更稳妥的做法是先把每个命中切片整理为统一记录:保留原文、来源文档、定位信息和检索分数;组装时再从同一批记录投影出模型上下文与前端引用。这样模型看到的是紧凑文本,读者看到的是可回溯的来源片段,两者不会因为排序或截断发生错位。
参考资料入口:https://huggingface.co/docs/transformers/main/chat_template_tools_and_documents
先把来源当成切片的一部分
一个切片至少要回答三个问题:它来自哪份文档、在文档中的什么位置、为什么被召回。只有正文文本而没有这些字段,后续即使生成了“参考来源”,也只能凭标题猜测,无法定位到真正的段落。
建议把内部记录设计成稳定的数据对象。source_id 用于跨切片归并,chunk_id 用于定位单个切片,locator 可以是页码、章节、段落编号或 URL 片段。score 只用于排序,不应被直接当成答案可信度。

只拼文本的旧写法为什么容易丢引用
最短的实现通常是遍历命中结果,把每个 text 用换行连接起来,再把连接后的字符串交给模型。这种写法能快速看到回答,却把标题、页码、URL 和切片边界一起丢掉了;当两个切片来自同一文档时,前端还可能展示两条重复来源。
另一个问题是排序与展示各做一遍。上下文层按分数截取前五段,展示层又按文档标题排序,模型回答中的“来源 2”就不一定对应界面上的第二条来源。解决方式不是让模型自己输出编号,而是由组装层先分配稳定的引用编号。
from dataclasses import dataclass
from html import escape
@dataclass
class ChunkRecord:
# 统一记录让上下文和引用共享同一份来源信息。
chunk_id: str
source_id: str
title: str
text: str
locator: str
score: float
def assemble_sources(hits: list[ChunkRecord], limit: int = 5) -> tuple[str, list[dict]]:
# 先按分数排序,再用 chunk_id 保证相同分数时结果稳定。
ordered = sorted(hits, key=lambda item: (-item.score, item.chunk_id))
chosen: list[ChunkRecord] = []
seen_sources: set[str] = set()
for hit in ordered:
# 同一文档优先保留最高分切片,避免引用列表重复占位。
if hit.source_id in seen_sources:
continue
chosen.append(hit)
seen_sources.add(hit.source_id)
if len(chosen) == limit:
break
context_parts: list[str] = []
citations: list[dict] = []
for index, hit in enumerate(chosen, start=1):
citation_id = f"S{index}"
# 编号由组装层产生,模型只需在回答中引用已有编号。
context_parts.append(f"[{citation_id}] {hit.title}\n{hit.text}")
citations.append({
"id": citation_id,
"source_id": hit.source_id,
"title": hit.title,
"locator": hit.locator,
"snippet": escape(hit.text[:180]),
})
return "\n\n".join(context_parts), citations
这段代码刻意把 context 和 citations 放在同一个循环里生成。实际项目中可以按业务需要保留同一文档的多个互补片段,但应让去重规则明确写在组装层,而不是交给模板或前端临时判断。
把一批记录投影成两种结果
检索记录是内部模型,模型上下文和界面引用则是两个不同的投影。上下文需要标题和片段正文,重点是短、清晰、能被模型识别;引用对象需要标题、来源标识、定位信息和短摘录,重点是能让读者回到原文。两者使用同一个 citation_id,但不要把内部所有字段都塞进 prompt。
如果使用支持文档列表的模型模板,可以把每条记录投影为包含标题和内容的文档对象;如果使用普通聊天模板,也可以把编号写进上下文文本。无论采用哪一种形式,编号都应由本地组装逻辑产生,不能依赖模型临时编造。

截断和缺失元数据要有明确规则
上下文预算不足时,应该先减少低分切片,再缩短单个片段,最后才考虑丢弃引用字段。不要先把所有正文截断后再重新编号,否则前端保存的摘录可能已经不是模型实际看到的内容。
缺少标题时可以使用文档 ID 作为临时显示名,缺少定位信息时显示“未提供定位”,但不要虚构页码或 URL。缺少 source_id 的记录不适合进入可回溯引用列表;可以保留在内部调试数据中,或在组装前过滤掉。
还要把“检索分数”和“来源可信度”分开。分数表示当前查询下的相似程度,来源可信度需要由文档级策略、更新时间、权限范围等业务信息决定。把二者混成一个百分比,很容易让用户误以为相似度就是事实正确率。
采用这套组装方式时记住三点
- 切片记录先完整,模型上下文和界面引用后投影。
- 去重、排序、截断和编号只在一个组装层决定。
- 缺失字段要诚实标记,不能为了好看补造定位或可信度。
常见问题
为什么不直接让模型输出来源链接?
模型可以根据上下文复述来源,但不适合负责生成真实链接和稳定编号。链接、定位和权限应来自检索记录,由应用层把模型引用编号映射回来源对象。
同一篇文档的多个切片是否一定要去重?
不一定。若多个切片分别包含定义和例外条件,可以都保留;去重的目标是避免相同来源无意义占位,而不是强行让每篇文档只出现一次。规则应根据上下文预算和引用展示空间决定。
引用摘录要不要和模型上下文完全一致?
核心事实应一致,但展示摘录可以更短,并保留足以定位的标题和位置。若上下文经过了二次裁剪,应该重新生成摘录,避免界面显示一段模型实际上没有读到的文字。
Hugging Face Inference Providers 选择模型路由的接入方式
- 上一篇
- Hugging Face Inference Providers 选择模型路由的接入方式
- 下一篇
- 多模态模型提取表格布局的结果约束
-
- 科技周边 · 人工智能 | 38分钟前 | 性能优化 · AI工程 · 缓存失效 提示词缓存 AI工程 Prompt Cache 稳定前缀
- 提示词缓存减少重复上下文开销的设计
- 263浏览 收藏
-
- 科技周边 · 人工智能 | 51分钟前 |
- 多模态模型提取表格布局的结果约束
- 359浏览 收藏
-
- 科技周边 · 人工智能 | 54分钟前 |
- Hugging Face Inference Providers 选择模型路由的接入方式
- 292浏览 收藏
-
- 科技周边 · 人工智能 | 12小时前 |
- Embedding 批量请求的长度和失败重试设计
- 383浏览 收藏
-
- 科技周边 · 人工智能 | 2天前 |
- RAG 文档切片怎样决定 overlap
- 278浏览 收藏
-
- 前端进阶之JavaScript设计模式
- 设计模式是开发人员在软件开发过程中面临一般问题时的解决方案,代表了最佳的实践。本课程的主打内容包括JS常见设计模式以及具体应用场景,打造一站式知识长龙服务,适合有JS基础的同学学习。
- 543次学习
-
- GO语言核心编程课程
- 本课程采用真实案例,全面具体可落地,从理论到实践,一步一步将GO核心编程技术、编程思想、底层实现融会贯通,使学习者贴近时代脉搏,做IT互联网时代的弄潮儿。
- 516次学习
-
- 简单聊聊mysql8与网络通信
- 如有问题加微信:Le-studyg;在课程中,我们将首先介绍MySQL8的新特性,包括性能优化、安全增强、新数据类型等,帮助学生快速熟悉MySQL8的最新功能。接着,我们将深入解析MySQL的网络通信机制,包括协议、连接管理、数据传输等,让
- 500次学习
-
- JavaScript正则表达式基础与实战
- 在任何一门编程语言中,正则表达式,都是一项重要的知识,它提供了高效的字符串匹配与捕获机制,可以极大的简化程序设计。
- 487次学习
-
- 从零制作响应式网站—Grid布局
- 本系列教程将展示从零制作一个假想的网络科技公司官网,分为导航,轮播,关于我们,成功案例,服务流程,团队介绍,数据部分,公司动态,底部信息等内容区块。网站整体采用CSSGrid布局,支持响应式,有流畅过渡和展现动画。
- 485次学习
-
- PubMedQA
- 深入了解PubMedQA生物医学问答数据集,涵盖其核心功能、使用方法及在临床决策、药物研发等场景的应用,助力提升NLP模型性能。
- 500次使用
-
- H2O EvalGPT
- H2O EvalGPT是H2O.ai推出的开源LLM评估平台,提供详细的大模型性能排行榜、行业特定基准测试及A/B测试功能,助您快速选择最适合项目的高性能大语言模型。
- 559次使用
-
- LMArena
- LMArena是加州大学伯克利分校推出的AI模型匿名评测平台。通过盲测投票机制,用户可对比不同大模型回答并生成实时排行榜,助力开发者优化模型及用户选择最佳AI工具。
- 587次使用
-
- HELM
- 深入了解斯坦福推出的HELM(Holistic Evaluation of Language Models)大模型评测体系。本文解析其核心功能、安装配置步骤及应用场景,涵盖准确性、公平性、鲁棒性等多维度指标,助力开发者全面优化语言模型性能。
- 539次使用
-
- MMBench
- MMBench是由上海人工智能实验室等机构联合推出的多模态基准测试平台,提供细粒度能力评估、大规模数据集及VLMEvalKit工具。本文详细介绍其核心功能、安装使用方法及应用场景,助力开发者全面评估多模态模型性能。
- 350次使用
-
- Redis 向量集合怎么落地:VADD、VDIM 与 VSIM 的维度和结果校验
- 2026-08-16 225浏览
-
- Obsidian Properties 怎么统一管理笔记元数据
- 2026-10-04 378浏览
-
- Obsidian 如何用属性视图批量整理笔记元数据
- 2026-10-09 494浏览
-
- Calibre怎样批量修正书籍作者排序
- 2026-10-13 421浏览
-
- RAG 召回评估实战:用向量检索和重排序减少答非所问
- 2026-06-12 174浏览
