大模型(LLMs)RAG ------ 关键痛点及对应解决方案
前言
受到 Barnett 等人的论文《Seven Failure Points When Engineering a Retrieval Augmented Generation System》的启发,本文将探讨论文中提到的七个痛点,以及在开发检索增强型生成(RAG)流程中常见的五个额外痛点。更为关键的是,我们将深入讨论这些 RAG 痛点的解决策略,使我们在日常 RAG 开发中能更好地应对这些挑战。
问题一:内容缺失问题
介绍一下内容缺失问题?
当实际答案不在知识库中时,RAG 系统往往给出一个貌似合理却错误的答案,而不是承认无法给出答案。这导致用户接收到误导性信息,造成错误的引导。
如何解决内容缺失问题?
-
优化数据源
- "输入什么,输出什么。"如果源数据质量差,比如充斥着冲突信息,那么无论你如何构建 RAG 流程,都不可能从杂乱无章的数据中得到有价值的结果。
-
改进提示方式
- 在知识库缺乏信息,系统可能给出错误答案的情况下,改进提示方式可以起到显著帮助。例如,通过设置提示"如果你无法确定答案,请表明你不知道"可以鼓励模型认识到自己的局限并更透明地表达不确定性。虽然无法保证百分百准确,但在优化数据源之后,改进提示方式是我们能做的最好努力之一。
问题二:错过排名靠前的文档
介绍一下错过排名靠前的文档问题?
有时候系统在检索资料时,最关键的文件可能并没有出现在返回结果的最前面。这就导致了正确答案被忽略,系统因此无法给出精准的回答。
如何解决错过排名靠前的文档问题?
-
重新排名检索结果
- 在将检索到的结果发送给大型语言模型(LLM)之前,对结果进行重新排名可以显著提升RAG的性能。LlamaIndex的一个笔记本展示了两种不同方法的效果对比:
- 直接检索前两个节点,不进行重新排名,这可能导致不准确的检索结果。
- 先检索前十个节点,然后使用CohereRerank进行重新排名,最后返回前两个节点,这种方法可以提高检索的准确性。
- 在将检索到的结果发送给大型语言模型(LLM)之前,对结果进行重新排名可以显著提升RAG的性能。LlamaIndex的一个笔记本展示了两种不同方法的效果对比:
-
调整数据块大小(chunk_size)和相似度排名(similarity_top_k)超参数
- chunk_size和similarity_top_k都是用来调控 RAG(检索增强型生成)模型数据检索过程中效率和效果的参数。改动这些参数能够影响计算效率与信息检索质量之间的平衡。以 LlamaIndex 为例,下面是一个示例代码片段。
param_tuner = ParamTuner(
param_fn=objective_function_semantic_similarity,
param_dict=param_dict,
fixed_param_dict=fixed_param_dict,
show_progress=True,
)
results = param_tuner.tune()
定义函数 objective_function_semantic_similarity,param_dict包含了参数chunk_size和top_k 以及它们推荐的值:
# 包含需要调优的参数
param_dict = {"chunk_size": [256, 512, 1024], "top_k": [1, 2, 5]}
# 包含在调整过程的所有运行中保持固定的参数
fixed_param_dict = {
"docs": documents,
"eval_qs": eval_qs,
"ref_response_strs": ref_response_strs,
}
def objective_function_semantic_similarity(params_dict):
chunk_size = params_dict["chunk_size"]
docs = params_dict["docs"]
top_k = params_dict["top_k"]
eval_qs = params_dict["eval_qs"]
ref_response_strs = params_dict["ref_response_strs"]
# 建立索引
index = _build_index(chunk_size, docs)
# 查询引擎
query_engine = index.as_query_engine(similarity_top_k=top_k)
# 获得预测响应
pred_response_objs = get_responses(
eval_qs, query_engine, show_progress=True
)
# 运行评估程序
eval_batch_runner = _get_eval_batch_runner_semantic_similarity()
eval_results = eval_batch_runner.evaluate_responses(
eval_qs, responses=pred_response_objs, reference=ref_response_strs
)
# 获取语义相似度度量
mean_score = np.array(
[r.score for r in eval_results["semantic_similarity"]]
).mean()
return RunResult(score=mean_score, params=params_dict)
问题三:脱离上下文 — 整合策略的限制
介绍一下脱离上下文 — 整合策略的限制问题?
论文中提到了这样一个问题:“虽然数据库检索到了含有答案的文档,但这些文档并没有被用来生成答案。这种情况往往出现在数据库返回大量文档后,需要通过一个整合过程来找出答案”。
如何解决脱离上下文 — 整合策略的限制问题?
- 优化检索策略
- 以 LlamaIndex 为例,LlamaIndex 提供了一系列从基础到高级的检索策略,以帮助我们在 RAG 流程中实现精准检索。欲了解所有检索策略的详细分类,可以查阅 retrievers 模块的指南。
- 从每个索引进行基础检索
- 进行高级检索和搜索
- 自动检索
- 知识图谱检索器
- 组合/分层检索器
- 更多其他选项!
- 以 LlamaIndex 为例,LlamaIndex 提供了一系列从基础到高级的检索策略,以帮助我们在 RAG 流程中实现精准检索。欲了解所有检索策略的详细分类,可以查阅 retrievers 模块的指南。
- 微调嵌入模型
- 如果你使用的是开源嵌入模型,对其进行微调是提高检索准确性的有效方法。LlamaIndex 提供了一份详尽的指南,指导如何一步步微调开源嵌入模型,并证明了微调可以在各项评估指标上持续改进性能。
(https://docs.llamaindex.ai/en/stable/examples/finetuning/embeddings/finetune_embedding.html
)
下面是一个示例代码片段,展示了如何创建微调引擎、执行微调以及获取微调后的模型:
- 如果你使用的是开源嵌入模型,对其进行微调是提高检索准确性的有效方法。LlamaIndex 提供了一份详尽的指南,指导如何一步步微调开源嵌入模型,并证明了微调可以在各项评估指标上持续改进性能。
finetune_engine &#