受到 Barnett 等人论文《构建检索增强生成系统的七大挑战》启发,本文将探讨论文中提及的七大挑战及在开发 RAG(检索增强生成)流程中常遇到的五个额外难题。更为重要的是,我们将深入讨论解决这些 RAG 难题的策略,以便我们在日常的 RAG 开发工作中能更有效地解决这些问题。
我偏好用 “难题” 而不是 “挑战” 来描述,因为这些问题都有对应的解决方案。我们应该在这些问题在我们的 RAG 流程中变成真正的挑战之前,尽量解决它们。
首先,我们来回顾一下论文中提到的七个难题,如下图所示。随后,我们还将讨论五个额外的难题及其解决策略。
01、内容缺失
知识库中缺少必要的上下文信息。当知识库没有包含正确答案时,RAG 系统可能会给出一个貌似合理但实际上错误的回答,而不是明确表示它不知道答案。这可能会导致用户接收到误导信息,从而感到挫败。
针对这一问题,我们提出了两种解决策略:
清洁数据源
俗话说,“垃圾进,垃圾出”。这就是说,如果输入的数据质量不高,比如说含有矛盾的信息,那么无论你的 RAG 流程构建得多么完善,都无法从这些低质量的输入中得到高质量的输出。这个策略不仅适用于当前的问题,而且适用于本文讨论的所有难题。确保数据的准确性和清晰性是任何有效 RAG 流程的基础。
优化提示策略
在缺乏知识库信息的情况下,通过更精准的提示,比如告诉系统 “如果你不确定答案,请明确表示你不知道”,可以明显提高系统回答问题时的准确性。这种方法虽然不能保证 100% 的准确率,但在清理数据之后,精心设计提示是提高输出质量的一种有效手段。
02、遗漏重要文档
在初始的检索步骤中,有时会漏掉关键文档,导致它们没有出现在系统返回的最顶端结果之中。这就意味着正确的答案可能被忽略了,使得系统无法准确回答问题。正如论文所指出的,“答案虽然在某个文档中,但因为排名不够高而没有呈现给用户”。
为此,我想到了两种可能的解决方法:
通过调整 chunk_size 和 similarity_top_k 参数优化检索效果
chunk_size 和 similarity_top_k 是控制 RAG 模型数据检索效率和效果的关键参数。适当调整这些参数,可以平衡计算效率与检索到的信息质量。我们在前一篇《利用 LlamaIndex 自动化超参数调优》中已经深入讨论了如何调整 chunk_size 和 similarity_top_k。
文章链接:https://levelup.gitconnected.com/automating-hyperparameter-tuning-with-llamaindex-72fdd68e3b90
下面是代码示例:
函数 objective_function_semantic_similarity 的定义如下所示,其中 param_dict 包含参数 chunk_size 和 top_k 及其推荐的值:
更多细节可以参考 LlamaIndex 发布的关于 RAG 超参数优化的完整教程:
https://docs.llamaindex.ai/en/stable/examples/param_optimizer/param_optimizer.html
检索结果的优化排序
在最终将检索结果提交给 LLM 前进行重排,已经被证明能显著提升 RAG 的性能。LlamaIndex 提供的一个示例笔记演示了两种情况的不同:
- 直接检索排名前两位的节点,不经过重排,可能导致不准确的检索结果。
- 检索排名前十位的节点,并利用 CohereRerank 进行重排,以返回排名最高的两个节点,从而获得更准确的检索结果。
此外,通过使用不同的嵌入技术和重排策略,可以进一步评估和提高检索器的性能,正如 Ravi Theja 在《提升 RAG 性能:选择最佳嵌入技术和重排模型》中所述。
文章链接:https://blog.llamaindex.ai/boosting-rag-picking-the-best-embedding-reranker-models-42d079022e83
你还可以对自定义的重排器进行微调,以获得更优的检索效果,Ravi Theja 在《通过微调 Cohere 重排器与 LlamaIndex 提升检索性能》中提供了详细的实现指南。
03、脱离上下文的挑战
即使在重排之后,有时关键文档仍未能融入生成答案所需的上下文中。这种情况通常出现在数据库返回大量文档,并需要通过一个整合过程来检索答案时。简而言之,即便包含答案的文档被检索到了,但未能有效整合进最终的回答中。
为了解决这个问题,我们可以采用以下策略:
优化检索策略
LlamaIndex 提供了一系列从基础到高级的检索策略,帮助我们在 RAG 流程中实现更精确的检索。你可以参考其检索器模块的指南。
指南:https://docs.llamaindex.ai/en/stable/module_guides/querying/retriever/retrievers.html
这里面详细列出了各种检索策略及其分类,包括:
- 每个索引的基础检索
- 高级检索与搜索
- 自动检索
- 知识图谱检索器
- 组合/分层检索器
- 等等
微调嵌入模型
如果你正在使用开源的嵌入模型,对其进行微调可以显著提升检索的准确度。LlamaIndex 提供了一套详细的微调开源嵌入模型指南,证明了微调能够在一系列评估指标上持续改善性能。
指南:https://docs.llamaindex.ai/en/stable/examples/finetuning/embeddings/finetune_embedding.html
下方是一个示例代码片段,介绍了如何创建微调引擎、执行微调过程以及获取微调后的模型:
04、信息提取困难
有时系统难以从提供的上下文中提取正确答案,特别是当上下文信息量过大时。关键细节可能会被忽略,影响回答的质量。这种情况往往出现在上下文中存在过多的干扰信息或信息矛盾时。
为此,我们可以尝试以下几种解决方法:
清洁数据
再次强调,清洁的数据至关重要。在质疑你的 RAG 流程效果之前,请先确保你的数据是准确和清晰的。
压缩提示
长上下文环境下的提示压缩技术首次在 LongLLMLingua 研究项目中被提出。现在,通过将其整合到 LlamaIndex 中,我们能够将 LongLLMLingua 作为一个节点后处理器来实现,该处理器会在数据检索步骤之后对上下文进行压缩处理,进而更高效地将数据送入 LLM 进行处理。
以下是设置 LongLLMLinguaPostprocessor 的示例代码片段,该代码利用 longllmlingua 包执行提示压缩操作。
更多详细信息,请参阅有关 LongLLMLingua 的完整笔记本:
https://docs.llamaindex.ai/en/stable/examples/node_postprocessor/LongLLMLingua.html#longllmlingua
长上下文重排
研究发现,当关键信息位于输入上下文的开始或结束时,通常能获得更好的性能。LongContextReorder 通过重新排序检索到的节点,解决了信息在中间部分可能 “丢失” 的问题,特别适用于需要大量 top-k 结果的情况。
以下是如何在构建查询引擎时,将 LongContextReorder 设置为你的 node_postprocessor 的示例代码片段。
想要了解更多详情,可以参考 LlamaIndex 提供的关于 LongContextReorder 的详细教程:
https://docs.llamaindex.ai/en/stable/examples/node_postprocessor/LongContextReorder.html
5、输出格式不正确
当系统忽略了以特定格式(例如表格或列表)提取信息的指令时,输出可能会出现格式错误。为了解决这一问题,我们提出了四种可能的解决方案:
优化提示
通过采用以下策略,你可以改善提示的效果并解决格式问题:
- 明确地指出你的指令。
- 简化请求,明确使用关键字。
- 提供示例以指导预期格式。
- 采用迭代提示,根据需要提出后续问题以细化结果。
输出解析
输出解析技术可以确保获得期望的输出格式:
- 为提示或查询提供格式化指令。
- 对 LLM 的输出进行解析。
LlamaIndex 支持与其他框架如 Guardrails 和 LangChain 的输出解析模块集成,增强了格式化输出的能力。
以下是一个示例代码片段,展示了你可以如何在 LlamaIndex 中使用 LangChain 的输出解析模块。
要了解更多细节,可参阅 LlamaIndex 关于输出解析模块的文档:
https://docs.llamaindex.ai/en/stable/module_guides/querying/structured_outputs/output_parser.html
Pydantic 程序
Pydantic 程序是一个将输入字符串转换为结构化 Pydantic 对象的框架。LlamaIndex 提供了几种 Pydantic 程序:
- 文本自动完成 Pydantic 程序:处理输入文本,并通过文本完成 API 结合输出解析,转换为用户定义的结构化对象。
- 函数调用 Pydantic 程序:将输入文本转换为用户指定的结构化对象,利用 LLM 的函数调用 API。
- 预封装 Pydantic 程序:旨在将输入文本转换为预定义的结构化对象。
参考以下 OpenAI 的 Pydantic 程序示例代码。
OpenAI JSON 模式
OpenAI JSON 模式允许我们将响应格式设置为 JSON,仅生成可以解析为有效 JSON 对象的字符串。这种模式强制输出格式的一致性,虽然它本身不直接提供针对特定模式的验证,但为格式化输出提供了一个可靠的框架。
这些解决方案提供了多种方式来确保输出格式符合预期,无论是通过改善提示、利用输出解析技术,还是通过使用 Pydantic 程序或启用 OpenAI 的 JSON 模式。
06、细节不够具体
当输出没有达到所需的具体性级别时,回答可能会缺乏必要的详细信息,经常需要进一步的查询来进行澄清。答案可能过于泛泛或模糊,无法有效地满足用户的需求。
为此,我们可以采用以下高级检索策略:
- 从小到大的信息聚合检索:从较小的信息片段开始,逐步扩展检索范围。
- 基于句子窗口的检索:围绕关键词进行窗口检索,提取相关句子。
- 递归检索:基于初始检索结果,再次执行检索以获取更深层次的信息。
07、输出不完整
有时输出虽不完全错误,但却未能提供所有详细信息,尽管这些信息在上下文中是存在且可以获取的。例如,询问文档 A、B 和 C 讨论的主要方面时,分别询问每个文档可能更能确保获得全面的答案。
查询变换的技巧
在自动化知识获取(RAG)过程中,对比较类问题的处理往往不尽人意。一个有效提升 RAG 处理能力的策略是增设一个查询理解层,即在实际检索知识库之前进行一系列的查询变换。具体来说,我们有以下四种变换方式:
- 路由:在保留原始查询的同时,明确指出相关的工具子集,并指定这些为合适的工具。
- 查询重写:保留选定的工具,但以多种方式重新构造查询,应用于相同的工具集合。
- 子问题:将大的查询分解为几个小问题,每个问题针对特定工具,根据其元数据确定。
- ReAct 代理工具选择:基于原始查询确定使用哪个工具,并制定对该工具的具体查询。
采用 HyDE(假设文档嵌入)技术,可以通过生成假设的文档 / 答案,然后利用此假设文档进行嵌入查找而非原始查询,来改进查询重写。
这些策略提供了在面对输出不够具体或不完整时的高级检索和查询转换方法,旨在提高回答的质量和完整性。
8、数据摄入的扩展性问题
当数据摄入管道难以处理更大数据量时,可能会出现性能瓶颈和系统潜在故障,导致摄入时间延长、系统过载、数据质量问题及可用性限制。
为此,我们可以采取以下措施:
并行化数据摄入流程,LlamaIndex 提供了数据摄入的并行处理功能,能够显著加快文档处理速度,达到原有速度的多达 15 倍。通过设置并行工作线程的数量(num_workers),可以实现更高效的数据处理。
09、结构化数据的查询应答
对于复杂或含糊的查询,准确解释用户查询并检索相关结构化数据可能颇具挑战,尤其是在文本到 SQL 转换不够灵活和当前 LLM 处理这类任务的限制下。
LlamaIndex 为此问题提供了两种解决方案。
链式表格包(ChainOfTablePack)
基于 “链式表格” 概念的 LlamaPack,将链式思考与表格转换和表示结合起来,逐步转换表格,并在每一步向 LLM 展示修改后的表格。这种方法特别适合解决涉及多信息复杂表格单元的问题,通过有系统地处理数据直至找到正确的数据子集,提高了表格 QA 的效果。
混合自洽包(MixSelfConsistencyPack)
LLM 能以两种主要方式对表格数据进行推理:
- 通过直接询问进行文本推理
- 通过程序合成(如 Python、SQL 等)进行符号推理
依据 Liu 等人的研究《重新思考 LLM 如何理解表格数据》,LlamaIndex 创新性地开发了 MixSelfConsistencyQueryEngine。该引擎结合了文本与符号推理的结果,并通过自洽机制(即,多数投票法)实现了最先进(State of the Art,SoTA)的性能表现。以下是一个示例代码片段。
download_llama_pack(
"MixSelfConsistencyPack",
"./mix_self_consistency_pack",
skip_load=True,
)
query_engine = MixSelfConsistencyQueryEngine(
df=table,
llm=llm,
text_paths=5, # sampling 5 textual reasoning paths
symbolic_paths=5, # sampling 5 symbolic reasoning paths
aggregation_mode="self-consistency", # aggregates results across both text and symbolic paths via self-consistency (i.e. majority voting)
verbose=True,
)
response = await query_engine.aquery(example["utterance"])
欲了解更多细节,可以查阅:https://github.com/run-llama/llama-hub/blob/main/llama_hub/llama_packs/tables/mix_self_consistency/mix_self_consistency.ipynb
10、处理复杂 PDF 文档的数据提取
从嵌入的表格等复杂 PDF 文档中提取数据,尤其用于问答场景,传统的检索方法可能无法实现。我们需要更高级的方法来处理这种复杂的 PDF 数据提取。
嵌入表格的检索
LlamaIndex 通过 EmbeddedTablesUnstructuredRetrieverPack 提供了一个解决方案,该方案利用 Unstructured。io 从 HTML 文档中解析出嵌入的表格,构建节点图,再通过递归检索根据用户问题检索表格。如果你手头是 PDF 文件,可以使用 pdf2htmlEX 工具将 PDF 转换为 HTML,以便不丢失任何文本或格式进行处理。
以下是如何下载、初始化及运行 EmbeddedTablesUnstructuredRetrieverPack 的示例代码片段。
# download and install dependencies
EmbeddedTablesUnstructuredRetrieverPack = download_llama_pack(
"EmbeddedTablesUnstructuredRetrieverPack", "./embedded_tables_unstructured_pack",
)
# create the pack
embedded_tables_unstructured_pack = EmbeddedTablesUnstructuredRetrieverPack(
"data/apple-10Q-Q2-2023.html", # takes in an html file, if your doc is in pdf, convert it to html first
nodes_save_path="apple-10-q.pkl"
)
# run the pack
response = embedded_tables_unstructured_pack.run("What's the total operating expenses?").response
display(Markdown(f"{response}")
11、备用模型
在使用 LLM 时,可能会遇到比如 OpenAI 模型的速率限制错误等问题。在主模型出现故障时,你需要一个或多个备用模型作为后备。
Neutrino 路由器
Neutrino 路由器是一个 LLM 集合,可以将查询智能地路由到最适合的模型,以优化性能、成本和延迟。Neutrino 支持十几种模型,你可以在 Neutrino 仪表板中自定义选择模型或使用包含所有支持模型的默认路由器。
LlamaIndex 已经通过其 llms 模块中的 Neutrino 类,加入了对 Neutrino 的支持。
from llama_index.llms import Neutrino
from llama_index.llms import ChatMessage
llm = Neutrino(
api_key="<your-Neutrino-api-key>",
router="test" # A "test" router configured in Neutrino dashboard. You treat a router as a LLM. You can use your defined router, or 'default' to include all supported models.
)
response = llm.complete("What is large language model?")
print(f"Optimal model: {response.raw['model']}")
OpenRouter
作为一个统一的 API 接口,OpenRouter 允许访问任何 LLM,它能够找到任何模型的最低价格,并在主要服务宕机时提供备用选项。OpenRouter 的主要优势包括价格竞争、标准化的 API 接口和模型使用频率的比较。
通过这些高级工具和策略,我们可以有效地解决复杂 PDF 数据提取的挑战和在模型遇到问题时保持系统的稳定性和可靠性。
12、LLM 的安全问题
处理提示注入、不安全输出以及防止敏感信息泄露等问题,是每位 AI 架构师和工程师面临的关键挑战。
Llama Guard:保护 LLM 的新工具
基于 7-B Llama 2,Llama Guard 被设计用于通过检查输入(通过提示分类)和输出(通过响应分类)为 LLM 分类内容。类似于 LLM 的工作方式,Llama Guard 生成文本结果,用以确定特定的提示或响应是否被视为安全或不安全。此外,如果它根据某些政策识别出内容为不安全,它将列出内容违反的具体子类别。
LlamaIndex 提供了 LlamaGuardModeratorPack,使开发者能够在下载和初始化包之后,通过一行代码调用 Llama Guard 来调节大语言模型的输入/输出。
实现辅助功能 moderate_and_query 的代码如下:
在下面的示例中,我们看到一个查询因为违反了我们设置的第 8 类规则而被标记为不安全。
13、总结
我们研究了在开发检索增强生成(RAG)系统时遇到的 12 个主要难题(包括原论文中的 7 个和我们额外发现的 5 个),并提出了针对每个难题的解决策略。
通过将这 12 个挑战及其建议的解决方法并列在一张表中,我们现在可以更直观地理解这些问题及其对策:
尽管这份清单不可能涵盖所有内容,但目的在于揭示 RAG 系统设计与实现过程中的复杂挑战。我希望通过此举增进对这些挑战的深刻理解,并激励大家开发出更为强大且适合用于生产环境的 RAG 应用。
如何学习AI大模型?
作为一名热心肠的互联网老兵,我决定把宝贵的AI知识分享给大家。 至于能学习到多少就看你的学习毅力和能力了 。我已将重要的AI大模型资料包括AI大模型入门学习思维导图、精品AI大模型学习书籍手册、视频教程、实战学习等录播视频免费分享出来。
这份完整版的大模型 AI 学习资料已经上传CSDN,朋友们如果需要可以微信扫描下方CSDN官方认证二维码免费领取【保证100%免费
】
一、全套AGI大模型学习路线
AI大模型时代的学习之旅:从基础到前沿,掌握人工智能的核心技能!
二、640套AI大模型报告合集
这套包含640份报告的合集,涵盖了AI大模型的理论研究、技术实现、行业应用等多个方面。无论您是科研人员、工程师,还是对AI大模型感兴趣的爱好者,这套报告合集都将为您提供宝贵的信息和启示。
三、AI大模型经典PDF籍
随着人工智能技术的飞速发展,AI大模型已经成为了当今科技领域的一大热点。这些大型预训练模型,如GPT-3、BERT、XLNet等,以其强大的语言理解和生成能力,正在改变我们对人工智能的认识。 那以下这些PDF籍就是非常不错的学习资源。
四、AI大模型商业化落地方案
作为普通人,入局大模型时代需要持续学习和实践,不断提高自己的技能和认知水平,同时也需要有责任感和伦理意识,为人工智能的健康发展贡献力量。