当前位置:   article > 正文

彻底改变聊天机器人的性能:释放三种有效的 RAG 增强策略_sentenceembeddingoptimizer

sentenceembeddingoptimizer

原文链接:Revolutionizing Chatbot Performance: Unleashing Three Potent Strategies for RAG Enhancement

2024 年 1 月 15 日

图片

在深入研究 RAG 机器人系列的最后一章之前,一些正在逐章构建聊天机器人的人可能会发现自己在努力解决一些问题。例如,如果有人不需要快如闪电的回复,而是需要更精确的回答,特别是在医疗聊天机器人等场景中,该怎么办?

今天,我们将探讨三种不同的技术,旨在提高聊天机器人在特定技能方面的整体表现。需要注意的是,在本节中,我们不会使用开源库或工具。这种偏离是有意为之,因为本文主要围绕性能和优化展开。虽然对于聊天机器人的功能来说这些都是可有可无的,但这些考虑因素都是为了满足对性能有特殊要求的用户和公司的需要。

在整个讨论过程中,我将用代码片段来说明每种技术。值得一提的是,所有提供的代码片段都可以无缝集成到前面文章中的代码中,确保无障碍实施。如果您发现这些示例对您的机器人有用,请随时将它们纳入您的项目。

为方便您探索这些概念,本文底部的 Google Colab Notebook 提供了所有代码片段,方便您公开访问。通过该资源,您可以对示例进行实验,并将其无缝融入聊天机器人开发流程。探索、调整并增强您的聊天机器人体验!

Agent

图片

一个agent可以被比喻为一个装备了多样化工具的主管,能够为给定的任务选择最合适的工具。agent的使用极大地提高了RAG(检索增强生成)系统的响应质量。作为一个平台,LlamaIndex提供了各种agent,包括ReAct agent,OpenAI agent和自定义agent。

在探索这些选项的过程中,我亲自测试了每一个选项,根据我的经验,我发现目前最有效的选择是基础的 OpenAI Agent 或最先进的 ContextRetrieverOpenAIAgent。如果您有兴趣深入了解每种agent的细微差别、优缺点,我建议您参考 Llama Index Docs 中的全面文档。该资源详细介绍了不同agent之间的差异,有助于根据您的具体需求做出明智的决定。

现在,让我们继续测试ContextRetrieverOpenAIAgent。为了启动这一过程,我们将启动建立索引的步骤。在本例中,我将选择快速方法,因为在前几章中,我们已经探索了使用各种技术建立索引的其他方法。

  1. from llama_index import VectorStoreIndex, SimpleDirectoryReader
  2. from llama_index.tools import QueryEngineTool, ToolMetadata
  3. documents = SimpleDirectoryReader("data").load_data()
  4. index = VectorStoreIndex.from_documents(documents)
  5. query_engine = index.as_query_engine();

在初始化 ContextRetrieverOpenAIAgent 之后,下一个关键步骤涉及定义 QueryEngineTool 数组。从本质上讲,QueryEngineTool 数组是一种分组机制,可用于全面描述和管理所有索引。该功能带来了对多索引功能的正式支持。

将这个索引数组想象成提供给我们的agent的 "工具 "库,以便成功执行给定任务(无论是查询还是聊天交互)。有了这一系列工具,agent就能自主选择最合适的工具来完成手头的任务。它引入了动态元素,允许agent根据每次交互的具体要求调整和优化其性能。

通过利用 QueryEngineTool 阵列,我们为agent提供了一个多功能工具包,增强了其在不同场景中有效导航和响应的能力。这种周到的工具管理方法与优化 RAG 系统性能并确保无缝、适应性强的用户体验这一总体目标相一致。

  1. query_engine_tools = [
  2.     QueryEngineTool(
  3.         query_engine=query_engine,
  4.         metadata=ToolMetadata(
  5.             name="basic_rules",
  6.             description=(
  7.                 "the basic game rules and description"
  8.             ),
  9.         ),
  10.     ),
  11. ]

随后,我们继续创建agent。值得注意的是,我们在这一步中加入了 "similarity_top_k "字段。通过这个字段,我们指示 RAG 将 VectorStore 中与我们的搜索一致的前 3 个元素视为上下文。如需深入了解这方面的内容,我建议您参阅本系列的第一章,在那里我们将深入探讨 RAG 架构。

此外,在agent创建过程中,我们引入了 "verbose "字段。通过设置该字段,我们可以启用自动日志记录功能,以透明的方式查看正在进行的进程。这对于理解agent的操作和诊断可能出现的任何问题都是非常有价值的。自动日志是一种有用的资源,能让人深入了解agent的内部运作,便于排除故障,并确保更顺畅的开发和部署体验。

  1. from llama_index.agent import ContextRetrieverOpenAIAgent
  2. context_agent = ContextRetrieverOpenAIAgent.from_tools_and_retriever(
  3.     query_engine_tools,
  4.     index.as_retriever(similarity_top_k=3),
  5.     verbose=True,
  6. )

现在是最后一部分,我们在这里生成回复:

  1. response = context_agent.chat("What is the game about?")
  2. print(response)

太棒了 通过这第一项技术,我们不仅深入了解了agent的基本概念,还开始迅速探索 LlamaIndex 中供我们使用的各种agent。通过了解 ReAct agent、OpenAI agent和自定义agent等不同类型的agent,我们为做出明智决策奠定了基础。

此外,我们还深入研究了这些知识的实际应用,特别是选择了我认为的最佳方案--基础型 OpenAI agent或创新型 ContextRetrieverOpenAIAgent。这为我们利用这些agent的力量来提高 RAG 系统的性能和响应质量奠定了基础。

从本质上讲,这项技术是一个宝贵的基础,它让我们掌握了在agent环境中进行导航、做出明智选择以及优化 RAG 实施以获得卓越效果的诀窍。敬请期待我们深入探讨完善和微调聊天机器人功能的复杂性!

降低成本

图片

需要仔细考虑的一个不可或缺的方面是基础设施成本。随着应用程序用户群的扩大,相关费用也会迅速攀升。为了减轻这一挑战,我们正在实施一种称为 "提示压缩 "的策略。在前面的文章中,我们了解到 RAG 要发挥作用,需要向语言模型传递一个自定义提示,其中包括从矢量存储(VectorStore)中获取的 top_k 节点。输入提示和输出都会产生成本,我们的目标是减少这两方面的成本。

为了压缩输入提示,我们将利用 SentenceEmbeddingOptimizer 类。该类在压缩 top_k 节点的文本方面起着关键作用。它是如何做到这一点的呢?通过使用另一种语言模型!我们有很多选择。我建议考虑经典的 Gpt-3.5 或 LlmLingua 模型。前者性价比高,运行速度快,而后者是开放源代码,需要花费更多精力在机器上进行设置和维护。如果您预计会有数百万的庞大用户群,那么选择 LlmLingua 可能会因其成本效益而更有优势。

不过,在本例中,我们将探索 Gpt 实现。设置与我们之前的过程类似,只是增加了少量但很关键的代码:

  1. from llama_index.postprocessor import SentenceEmbeddingOptimizer
  2. query_engine = index.as_query_engine(
  3.     node_postprocessors=[SentenceEmbeddingOptimizer(percentile_cutoff=0.5)]
  4. )
  5. query_engine_tools = [
  6.     QueryEngineTool(
  7.         query_engine=query_engine,
  8.         metadata=ToolMetadata(
  9.             name="basic_rules",
  10.             description=(
  11.                 "the basic game rules and description"
  12.             ),
  13.         ),
  14.     ),
  15. ]
  16. context_agent = ContextRetrieverOpenAIAgent.from_tools_and_retriever(
  17.     query_engine_tools,
  18.     index.as_retriever(similarity_top_k=3),
  19.     verbose=True,
  20. )
  21. response = context_agent.chat("Give me in a short answer how to play the first turn?")
  22. print(response)

这一策略的关键在于一个名为 "percentile_cutoff "的参数。该参数对指导语言模型如何积极压缩上下文至关重要。在本方案中,我们将其设置为 50%,从而有效地将输入提示的成本降低了一半。这是一个强大的成本优化工具,但需要注意的是:将 percentile_cutoff 设为 60-65% 以上可能会导致回复混乱或不够详细。取得适当的平衡对于保持模型输出的完整性和质量至关重要。

输出

至于输出,这是一个相对简单的方面。虽然没有降低成本的直接方法,但您可以影响模型回复的长度。通过提示模型提供简洁的回复,就能从本质上减少输出代币的数量,从而提高操作的成本效益。这是管理 RAG 基础架构相关费用的一种微妙而有效的方法。

  1. response = context_agent.chat("Give me in a short answer how to play the first turn?")
  2. print(response)

我承认这种方法可能不是最终的解决方案,但实践证明它非常有效。采用这种方法大大减少了语言模型的输出量,有助于提高运行效率和成本效益。有时,简洁本身就蕴含着高明之处,在这种情况下,促使模型做出更简短的回答,已被证明是实现减少产出的一种务实而成功的策略。

重新排序

图片

从本质上讲,重新排序涉及根据特定标准或附加信息对项目列表进行重新排序或重新评估。重新排序被广泛应用于信息检索、自然语言处理和机器学习等不同领域,其主要目的是通过加入补充特征或完善初始排序来提高项目的排序。在自然语言处理领域,重排在机器翻译或语言生成系统中得到了应用。在生成一组可能的输出后,重排会根据额外的语言特征或上下文来选择最合适或最流畅的选项。

在前面的例子中,我们选择了 top_k 3 个值,并将它们传递给语言模型。但是,为了实现重新排序,我们扩大了范围,以考虑更多的结果(例如 10 个)。这些结果在提交给语言模型之前都要经过重新排序的过程,从而提高回复的整体质量。

事实证明,重新排序是一个非常强大的工具,如果与agent相结合,就能大大提高生成回复的质量。有两种重新排序方法值得考虑:

  1. Cohere重排:这是一个非常有效的工具,目前被认为是最好的工具之一。不过,由于 Cohere 需要对定制模型进行培训和部署,因此成本不菲。如果成本不是制约因素,建议选择此工具。

  2. 使用另一个 LLM 模型重新排名:这是一种成本效益更高但功能同样强大的替代方法。它尤其适用于敏感数据(如医院数据)不是主要考虑因素的情况。

在本讨论中,我们将深入探讨第二种方法。要启动这一过程,我们必须首先重建索引,并将上下文保存在服务上下文中。该上下文是为 Reranker 模型提供必要信息的基础。让我们继续这一关键步骤。

  1. from llama_index import (
  2.     VectorStoreIndex,
  3.     SimpleDirectoryReader,
  4.     ServiceContext,
  5. )
  6. from llama_index.llms import OpenAI
  7. documents = SimpleDirectoryReader("data").load_data()
  8. llm = OpenAI(temperature=0, model="gpt-3.5-turbo")
  9. service_context = ServiceContext.from_defaults(llm=llm, chunk_size=512)
  10. index = VectorStoreIndex.from_documents(
  11.     documents, service_context=service_context
  12. )

在重新排名策略中,我们选择了简单的 GPT-3.5-turbo 模型。不过,需要注意的是,基准测试表明 Ministral Experts 模式的性能更好。如果您在之前的文章中已经设置并实施了 Ministral Experts 模型,建议您坚持使用该模型,以保持一致性并获得最佳性能。

选择了合适的语言模型后,下一步就是定义重判定器:

  1. from llama_index.postprocessor import LLMRerank
  2. reranker = LLMRerank(
  3.         choice_batch_size=5,
  4.         top_n=3,
  5.         service_context=service_context,
  6.   )

如前所述,与第一个示例一样,重排器将对前 3 个项目进行操作,但现在是从一个更大的数据池中提取的。接下来,我们将构建查询引擎,以检索 3 个以上的值。检索多少数据取决于您的具体要求。关键是要取得平衡--避免传递过多的数据,因为这会产生更高的成本。不过,提供更多数据通常会产生更好的结果。出于测试目的,我们选择前 10 个结果:

  1. query_engine = index.as_query_engine(
  2.     similarity_top_k=10,
  3.     node_postprocessors=[reranker],
  4.     response_mode="refine",
  5. )

请注意字段 response_mode="refine"-这表示速度较慢但非常有效的方法。它的运行方式类似于agent,优先考虑质量而不是延迟。本章的重点是提高响应质量,因此这种方法符合我们当前的目标。

有了这些配置,我们就可以进行进一步的测试,以评估重新排序对响应整体质量的影响。

  1. response = query_engine.query(
  2.     "What is the best strategy for the first turns?",
  3. )
  4. print(response)

非常棒!事实证明,反应令人印象深刻,凸显了所实施策略的有效性。

在这篇文章中,我们涉及了许多概念,并介绍了提高 RAG 性能的三种策略。现在,该轮到你了--在所讨论的三种策略中,你打算尝试哪一种?无论您是否已经熟悉这些技术,本文都为您提供了进一步探索的综合资源。

如果您有兴趣深入了解代码并亲自进行实验,可以在这里找到文章的代码:Article Code [1]

相关链接

[1] https://colab.research.google.com/drive/1_uuWTDuyvjxf6QdM-dWtUnLxy9-CgFre?usp=sharing

声明:本文内容由网友自发贡献,不代表【wpsshop博客】立场,版权归原作者所有,本站不承担相应法律责任。如您发现有侵权的内容,请联系我们。转载请注明出处:https://www.wpsshop.cn/w/羊村懒王/article/detail/360600
推荐阅读
相关标签
  

闽ICP备14008679号