AI知识库

53AI知识库

学习大模型的前沿技术与行业应用场景


RAG 开发的痛点及解决方案
发布日期:2024-06-16 17:44:36 浏览次数: 2053 来源:Tech For Fun


受 Barnett 等人撰写的论文《 设计 RAG 系统时的七个失败点 》的启发,在本文中探讨论文中提到的七个失败点以及开发 RAG 流水线过程中的另外五个常见痛点。更重要的是,我们将深入探讨这些 RAG 痛点的解决方案,以便在日常 RAG 开发中更好地解决这些痛点。

本文使用 " 痛点 " 而不是 " 失败点 " ,主要是因为这些痛点都有相应的解决方案。让我们在它们成为我们 RAG 流水线中的失败点之前,设法解决它们。

首先,让我们检查上述论文中提到的七个痛点;见下图。然后,我们将添加另外五个痛点及建议的解决方案。

痛点 1 :内容缺失

知识库中缺少上下文。当实际答案不在知识库中时, RAG 系统会提供一个似是而非的错误答案,而不是说它不知道。用户会收到误导性信息,从而产生挫败感。有两个解决方案:

清理数据

垃圾进,垃圾出。如果你的源数据质量很差,例如包含相互矛盾的信息,那么无论你建立了多么完善的 RAG 流水线,它也无法从你输入的垃圾中神奇地输出黄金。本文提出的解决方案不仅可以解决这一痛点,还可以解决本文列出的所有痛点。干净的数据是任何运行良好的 RAG 流水线的先决条件。

有一些常见的数据清理策略,仅举几例:

  • 去除噪音和无关信息:这包括删除特殊字符、停止词( "the " 和 "a " 等常用词 )和 HTML 标记。

  • 识别并纠正错误:这包括拼写错误、错别字和语法错误。拼写检查程序和语言模型等工具都能在这方面提供帮助。

  • 重复数据删除:删除可能影响检索过程的重复记录或类似记录。

Unstructured.io 在其核心库中提供了一系列清理功能,可帮助满足此类数据清理需求。值得一试。

更好的提示词

由于知识库中缺乏信息,系统可能会提供一个似是而非但不正确的答案,在这种情况下,更好的提示词功能可以提供很大帮助。通过 " 如果你不确定答案,请告诉我你不知道 " 等提示来指导系统,可以鼓励模型承认其局限性,并更透明地传达不确定性。虽然不能保证百分之百的准确性,但在清理数据之后,精心设计提示语是最好的方法之一。

痛点 2 :错过排名靠前的文档

在初始检索过程中丢失内容。重要文档可能不会出现在系统检索组件返回的最前结果中。正确答案被忽略,导致系统无法提供准确的回复。Barnett 的论文暗示: “ 问题的答案就在文档中,但排名不够靠前,无法返回给用户 ” 。有两个建议的解决方案:

chunk_size 和 similarity_top_k 超参微调

在 RAG 模型中, chunk_size 和 similarity_top_k 都是用于管理数据检索过程的效率和效果的参数。调整这些参数会影响计算效率和检索信息质量之间的权衡。文章《 使用 LlamaIndex 自动调整超参数 》中探讨了调整chunk_size similarity_top_k 这两个参数的细节。请参阅下面的示例代码片段:

    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 ,以及相应的建议值:

       # contains the parameters that need to be tuned param _ dict = {  "chunk _ size" :  [ 256 512 1024  ] ,  "top _ k" :  [  ]  }
       # contains parameters remaining fixed across all runs of the tuning process 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"  ] 
       # build index index = _ build _ index ( chunk _ size , docs )
       # query engine query _ engine = index.as _ query _ engine ( similarity _ top _ k=top _ k )
       # get predicted responses pred _ response _ objs = get _ responses  ( eval _ qs , query _ engine , show _ progress= True  ) 
       # run evaluator 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  ) 
       # get semantic similarity metric mean _ score = np.array  (  [  r.score for in eval _ results  [  "semantic _ similarity"  ]  ]  ).mean  (  ) 
      return RunResult ( score=mean _ score , params=params _ dict )

      更多详情,请参阅 LlamaIndex 关于 RAG 超参优化的完整笔记。

      重新排序

      在将检索结果发送到 LLM 之前对其重新排序可显著提高 RAG 性能。LlamaIndex 笔记展示了这两者之间的区别:

      • 不使用重新排序器直接检索前 2 个节点,检索结果不准确。

      • 通过检索前 10 个节点并使用 CohereRerank 重排序并返回前 2 个节点来实现精确检索。

        import os from llama _ index.postprocessor.cohere _ rerank import CohereRerank 
        api _ key = os.environ  [  "COHERE _ API _ KEY"  ] cohere _ rerank = CohereRerank ( api _ key=api _ key , top _ n=2 ) # return top 2 nodes from reranker 
        query _ engine = index.as _ query _ engine  ( similarity _ top _ k=10 ,  # we can set a high top _ k here to ensure maximum relevant retrieval node _ postprocessors= [ cohere _ rerank ],  # pass the reranker to node _ postprocessors  ) 
        response = query _ engine.query  (  "What did Sam Altman do in this essay?"  ) 

        还可以使用各种嵌入和重定级器来评估和提高检索器的性能,详见《 提升 RAG :挑选最佳嵌入和重定级器模型》( Boosting RAG : Picking the Best Embedding & Reranker models ),作者:Ravi Theja 。

        此外,还可以微调自定义重排序器,以获得更好的检索性能,具体实现方法详见 Ravi Theja 所著的《利用 LlamaIndex 微调 Cohere 重排序器以提高检索性能》( Improving Retrieval Performance by Fine-tuning Cohere Reranker with LlamaIndex )。

        痛点 3 :不符合上下文 -- 整合策略的局限性

        重新排序后上下文缺失。Barnett的论文对这一点进行了定义: “ 从数据库中检索到了包含答案的文档,但没有将其纳入生成答案的上下中。当从数据库中返回许多文档时,就会出现这种情况,这时就需要进行整合以检索答案 ” 。

        除了上节所述的添加重排器和微调重排器外,我们还可以探索以下建议的解决方案:

        调整检索策略

        LlamaIndex 提供了一系列从基本到高级的检索策略,帮助我们在 RAG 流水线中实现精确检索。请查看检索模块指南,了解所有检索策略的综合列表,这些策略分为不同的类别。

        • 每个索引的基本检索

        • 高级检索和搜索

        • 自动检索

        • 知识图谱检索器

        • 合成 / 分层检索器

        • 以及其他策略类别


        微调嵌入

        如果你使用的是开源嵌入模型,对嵌入模型进行微调是实现更精确检索的好方法。LlamaIndex 提供了对开源嵌入模型进行微调的分步指南,证明对嵌入模型进行微调可以持续改善评估指标套件中的各项指标。

        请参阅下面的示例代码片段,了解如何创建微调引擎、运行微调并获取微调后的模型:

          finetune _ engine = SentenceTransformersFinetuneEngine  ( train _ dataset , model _ id=  "BAAI/bge-small-en" , model _ output _ path=  "test _ model" , val _ dataset=val _ dataset ,  ) 
          finetune _ engine.finetune  (  ) 
          embed _ model = finetune _ engine.get _ finetuned _ model  (  ) 

          痛点 4 :未提取

          未提取上下文。系统难以从提供的上下文中提取正确答案,尤其是在信息量过大的情况下。关键细节被遗漏,影响了答案的质量。Barnett的论文暗示 " 当上下文中存在过多噪音或相互矛盾的信息时,就会出现这种情况。让我们来探讨三个建议的解决方案:

          清理数据

          这个痛点是不良数据的另一个典型受害者。我们怎么强调清洁数据的重要性都不为过!在指责 RAG 流水线之前,请先花时间清理数据。

          提示词压缩

          LongLLMLingua 研究项目 / 论文介绍了长上下设置中的提示词压缩。通过将其集成到 LlamaIndex 中,我们现在可以将 LongLLMLingua 作为节点后处理器来实现,它将在检索步骤后压缩上下文,然后再将其输入 LLM 。LongLLMLingua 压缩提示可以以更低的成本获得更高的性能。此外,整个系统的运行速度也会更快。

            from llama _ index.core.query _ engine import RetrieverQueryEngine from llama _ index.core.response _ synthesizers import CompactAndRefine from llama _ index.postprocessor.longllmlingua import LongLLMLinguaPostprocessor from llama _ index.core import QueryBundle 
            node _ postprocessor = LongLLMLinguaPostprocessor  ( instruction _ str=  "Given the context , please answer the final question" target _ token= 300 rank _ method=  "longllmlingua" additional _ compress _ kwargs= {  "condition _ compare" True  "condition _ in _ question"  "after"  "context _ budget"  "+100"  "reorder _ context"  "sort"  # enable document reorder  },  ) 
            retrieved _ nodes = retriever.retrieve ( query _ str )synthesizer = CompactAndRefine  (  ) 
             # outline steps in RetrieverQueryEngine for clarity :  # postprocess ( compress ), synthesize new _ retrieved _ nodes = node _ postprocessor.postprocess _ nodes  ( retrieved _ nodes , query _ bundle=QueryBundle ( query _ str=query _ str ) ) 
            print  (  "\n\n" . join  (  [  n.get _ content  (  ) for in new _ retrieved _ nodes  ]  )  ) 
            response = synthesizer.synthesize ( query _ str , new _ retrieved _ nodes )

            长上下文重排序

            一项研究发现,当关键数据位于输入上下文的开始或结束位置时,通常会产生最佳性能。LongContextReorder 就是为了解决这个 " 中间丢失 " 的问题而设计的,它可以对检索到的节点重新排序,这在需要大量 top-k 的情况下很有帮助。

            请参阅下面的示例代码片段,了解如何在构建查询引擎时将 LongContextReorder 定义为节点后处理器。更多详情,请参阅 LlamaIndex 关于 LongContextReorder 的完整笔记本。

              from llama _ index.core.postprocessor import LongContextReorder 
              reorder = LongContextReorder  (  ) 
              reorder _ engine = index.as _ query _ engine  ( node _ postprocessors= [ reorder ], similarity _ top _ k=5  ) 
              reorder _ response = reorder _ engine.query  (  "Did the author meet Sam Altman?"  ) 
              痛点 5 :格式错误

              输出格式错误。当以特定格式( 如表格或列表 )提取信息的指令被 LLM 忽视时,我们提出了四种解决方案供大家探讨:

              更好的提示词

              可以采用几种策略来改进提示并纠正这一问题:

              • 明确说明。

              • 简化要求并使用关键词。

              • 举例说明。

              • 迭代提示并提出后续问题。

              输出解析

              输出解析可用于以下方面,以帮助确保获得所需的输出:

              • 为任何提示 / 查询提供格式说明

              • 为 LLM 输出提供 “ 解析 ” 

              LlamaIndex 支持与其他框架( 如 Guardrails 和 LangChain )提供的输出解析模块集成。

              下面是 LangChain 输出解析模块的示例代码片段,可以在 LlamaIndex 中使用这些模块。更多详情,请查看 LlamaIndex 有关输出解析模块的文档。

                from llama _ index.core import VectorStoreIndex , SimpleDirectoryReader from llama _ index.core.output _ parsers import LangchainOutputParser from llama _ index.llms.openai import OpenAI from langchain.output _ parsers import StructuredOutputParser , ResponseSchema 
                 # load documents , build index documents = SimpleDirectoryReader  (  " .. /paul _ graham _ essay/data"  ).load _ data  (  ) index = VectorStoreIndex.from _ documents ( documents )
                 # define output schema response _ schemas =  [ ResponseSchema  ( name=  "Education" description=  "Describes the author's educational experience/background."  ) , ResponseSchema  ( name=  "Work" description=  "Describes the author's work experience/background."  ) ,  ] 
                 # define output parser lc _ output _ parser = StructuredOutputParser.from _ response _ schemas  ( response _ schemas  ) output _ parser = LangchainOutputParser ( lc _ output _ parser )
                 # Attach output parser to LLM llm = OpenAI ( output _ parser=output _ parser )
                 # obtain a structured response query _ engine = index.as _ query _ engine ( llm=llm )response = query _ engine.query  (  "What are a few things the author did growing up?"  ) print ( str ( response ))
                Pydantic 程序

                Pydantic 程序是一个多功能框架,可将输入字符串转换为结构化的 Pydantic 对象。LlamaIndex 提供几类 Pydantic 程序:

                • LLM 文本补全 Pydantic 程序:这些程序处理输入文本,并将其转换为用户定义的结构化对象,利用文本补全 API 结合输出解析。

                • LLM 函数调用 Pydantic 程序:这些程序利用 LLM 函数调用 API 获取输入文本,并将其转换为用户指定的结构化对象。

                • 预包装 Pydantic 程序:这些程序旨在将输入文本转换为预定义的结构化对象。

                下面是 OpenAI pydantic 程序的示例代码片段。欲了解更多详情,请查看 LlamaIndex 的 pydantic 程序文档,其中包含不同 pydantic 程序的笔记 / 指南链接。

                  from pydantic import BaseModel from typing import List 
                  from llama _ index.program.openai import OpenAIPydanticProgram 
                   # Define output schema ( without docstring )class Song  (  BaseModel  ) title : str length _ seconds : int 

                  class Album  (  BaseModel  ) name : str artist : str songs : List [ Song ]
                   # Define openai pydantic program prompt _ template _ str =  """\ Generate an example album , with an artist and a list of songs.\ Using the movie { movie _ name } as inspiration.\  """ program = OpenAIPydanticProgram.from _ defaults  ( output _ cls=Album , prompt _ template _ str=prompt _ template _ str , verbose= True  ) 
                   # Run program to get structured output output = program  ( movie _ name=  "The Shining" , description=  "Data model for an album."  ) 
                  OpenAI JSON 模式

                  OpenAI JSON 模式使我们能够将 response _ format 设置为{ "type" : "json _ object" }以启用响应的 JSON 模式。启用 JSON 模式后,模型将受限于只能生成解析为有效 JSON 对象的字符串。JSON 模式会强制执行输出格式,但无助于根据指定模式进行验证。更多详情,请查看 LlamaIndex 关于 OpenAI JSON 模式与数据提取函数调用的文档。

                  痛点 6 :具体程度不正确

                  输出的具体程度不正确。答复可能缺乏必要的细节或具体内容,往往需要后续询问才能澄清。答案可能过于模糊或笼统,无法有效满足用户的需求。

                  我们转向高级检索策略来寻求解决方案。

                  高级检索策略

                  当答案的粒度达不到你的期望时,可以改进检索策略。有助于解决这一痛点的一些主要高级检索策略包括

                  • 从小到大检索( https : //docs.llamaindex.ai/en/stable/examples/retrievers/auto _ merging _ retriever.html )

                  • 句子窗口检索( https : //docs.llamaindex.ai/en/stable/examples/node _ postprocessor/MetadataReplacementDemo.html )

                  • 递归检索( https : //docs.llamaindex.ai/en/stable/examples/query _ engine/pdf _ tables/recursive _ retriever.html )

                  有关7种高级检索 LlamaPacks 的更多详情,请参阅文章《 Jump-start Your RAG Pipelines with Advanced Retrieval LlamaPacks and Benchmark with Lighthouz AI 》。

                  痛点 7 :不完整

                  输出不完整。部分回答并没有错;但是,它们并没有提供所有的细节,尽管信息已经存在并且可以在上下文中获取。例如,如果有人问: “ 文档 A 、 B 和 C 中讨论的主要方面是什么? ” 为了确保答案的全面性,对每份文档进行单独查询可能会更有效。

                  查询转换

                  比较问题在最原始的 RAG 方法中表现尤为糟糕。提高 RAG 推理能力的一个好方法是添加查询理解层 -- 在实际查询向量存储之前添加查询转换。下面是四种不同的查询转换:

                  • 路由:保留初始查询,同时找出与之相关的适当工具子集。然后,将这些工具指定为合适的选项。

                  • 查询重写:保留选定的工具,但以多种方式重新制定查询,以便在同一组工具中应用。

                  • 子问题:将查询分解成几个较小的问题,每个问题针对不同的工具,由其元数据决定。

                  • ReAct Agent 工具选择:根据原始查询,确定要使用的工具,并制定在该工具上运行的特定查询。

                  请参阅下面的示例代码片段,了解如何使用 HyDE ( 假设文档嵌入 )这一查询重写技术。给定一个自然语言查询,首先生成一个假设文档 / 答案。然后使用该假设文档进行嵌入查找,而不是原始查询。

                     # load documents , build index documents = SimpleDirectoryReader  (  " .. /paul _ graham _ essay/data"  ).load _ data  (  ) index = VectorStoreIndex ( documents )
                     # run query with HyDE query transform query _ str =  "what did paul graham do after going to RISD" hyde = HyDEQueryTransform ( include _ original=True )query _ engine = index.as _ query _ engine  (  ) query _ engine = TransformQueryEngine ( query _ engine , query _ transform=hyde )
                    response = query _ engine.query ( query _ str )print ( response )

                    查看 LlamaIndex 的查询转换 Cookbook ,了解所有详细信息。

                    此外,还可以查看ulia Brezean u 的文章《 高级查询转换以改进 RAG 》,以获取关于查询转换技术的详细信息。


                    以上痛点均来自论文。现在,让我们来探讨 RAG 开发中常见的另外五个痛点及其建议的解决方案。

                    痛点 8 :数据摄取可扩展性

                    摄取流水线无法扩展到更大的数据量。RAG 流水线中的数据摄取可扩展性问题是指当系统难以有效管理和处理大量数据时出现的挑战,从而导致性能瓶颈和潜在的系统故障。此类数据摄取可扩展性问题会导致摄取时间延长、系统过载、数据质量问题和可用性受限。

                    摄取流水线并行化

                    LlamaIndex 提供摄取流水线并行处理功能,该功能可使 LlamaIndex 的文档处理速度提高 15 倍。请参阅下面的示例代码片段,了解如何创建摄取流水线( IngestionPipeline )并指定 num _ workers 以调用并行处理。查看 LlamaIndex 的完整笔记本,了解更多详情。

                       # load data documents = SimpleDirectoryReader ( input _ dir=  "./data/source _ files"  ).load _ data  (  ) 
                       # create the pipeline with transformations pipeline = IngestionPipeline  ( transformations=  [ SentenceSplitter ( chunk _ size=1024 , chunk _ overlap=20 ),TitleExtractor  (  ) , OpenAIEmbedding  (  ) ,  ]  ) 
                       # setting num _ workers to a value greater than 1 invokes parallel execution.nodes = pipeline.run ( documents=documents , num _ workers=4 )
                      痛点 9 :结构化数据质量保证

                      无法对结构化数据进行质量保证。准确解释用户查询以检索相关结构化数据可能很困难,尤其是在查询复杂或模糊、文本到 SQL 不灵活以及当前 LLM 在有效处理这些任务方面存在局限性的情况下。LlamaIndex 提供了两种解决方案:

                      Chain-of-table 

                      ChainOfTablePack 是基于 Wang 等人的创新性 " chain-of-table " 论文的 LlamaPack 。 " 表链 " 将思维链的概念与表转换和表示方法整合在一起。它使用一组受限的操作逐步转换表格,并在每个阶段将修改后的表格呈现给 LLM 。这种方法的一个显著优势是,它能够有条不紊地切割数据,直到识别出适当的子集,从而解决涉及包含多种信息的复杂表格单元格的问题,提高了表格质量保证的有效性。

                      有关如何使用 ChainOfTablePack 查询结构化数据的详细信息,请查看 LlamaIndex 的完整笔记(https : //github.com/run-llama/llama-hub/blob/main/llama _ hub/llama _ packs/tables/chain _ of _ table/chain _ of _ table.ipynb )。

                      混合自一致性包

                      LLM 可以通过两种主要方式对表格数据进行推理:

                      • 通过直接提示进行文本推理

                      • 通过程序合成( 如 Python 、 SQL 等 )进行符号推理

                      LlamaIndex 根据 Liu 等人撰写的论文《 Rethinking Tabular Data Understanding with Large Language Models 》,开发了混合自一致性查询引擎( MixSelfConsistencyQueryEngine ),通过自一致性机制(即多数票表决)汇总文本推理和符号推理的结果,并实现 SoTA 性能。请看下面的示例代码片段。查看 LlamaIndex 的完整笔记( https : //github.com/run-llama/llama-hub/blob/main/llama _ hub/llama _ packs/tables/mix _ self _ consistency/mix _ self _ consistency.ipynb ),了解更多详情。

                        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"  ]  ) 

                        痛点 10 :从复杂的 PDF 文档中提取数据

                        你可能需要从复杂的 PDF 文档中提取数据,例如从嵌入式表格中提取数据,用于问答。简单的检索无法从这些嵌入式表格中获取数据。需要一种更好的方法来检索此类复杂的 PDF 数据。

                        嵌入式表格检索

                        LlamaIndex 在 EmbeddedTablesUnstructuredRetrieverPack 中提供了一种解决方案,该 LlamaPack 使用 Unstructured.io 从 HTML 文档中解析出嵌入式表格,构建节点图,然后根据用户问题使用递归检索来索引 / 检索表格。

                        请注意,该程序包将 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 的集合,你可以将查询路由到它。它使用预测模型将查询智能地路由到最适合提示的 LLM ,在优化成本和延迟的同时最大限度地提高性能。Neutrino 目前支持十几种模型。如果你希望在支持的机型列表中添加新的机型,请联系他们的支持人员。

                          你可以创建一个路由器,在 Neutrino 面板上手动选择你喜欢的型号,或者使用 " 默认 " 路由器,其中包括所有支持的型号。

                          LlamaIndex 通过 llms 模块中的 Neutrino 类集成了对 Neutrino 的支持。请看下面的代码片段。更多详情,请访问 Neutrino AI 页面。

                            from llama _ index.llms.neutrino import Neutrino from llama _ index.core.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 

                            OpenRouter 是访问任何 LLM 的统一 API 。它能找到任何型号的最低价格,并在主主机宕机时提供后备服务。根据 OpenRouter 的文档,使用 OpenRouter 的主要好处包括:

                            • 从低价竞争中获益。OpenRouter 可以在数十家供应商中为每种型号找到最低价格。还可以让用户通过 OAuth PKCE 为自己的模型付费。

                            • 标准化 API 。在模型或提供商之间切换时,无需更改代码。

                            • 最好的模型将得到最广泛的使用。根据模型的使用频率和使用目的进行比较。

                            LlamaIndex 通过 llms 模块中的 OpenRouter 类集成了 OpenRouter 支持。请看下面的代码片段。查看 OpenRouter 页面上的更多详细信息。

                              from llama _ index.llms.openrouter import OpenRouter from llama _ index.core.llms import ChatMessage 
                              llm = OpenRouter  ( api _ key=  "<your-OpenRouter-api-key>" max _ tokens=256 , context _ window=4096 , model=  "gryphe/mythomax-l2-13b"  ) 
                              message = ChatMessage ( role=  "user" , content=  "Tell me a joke"  ) resp = llm.chat  (  [  message  ]  ) print ( resp )
                              痛点 12 :LLM 安全

                              如何对抗提示词注入、处理不安全输出、防止敏感信息泄露,这些都是每个人工智能架构师和工程师需要回答的迫切问题。

                              我们提出了两个解决方案:

                              NeMo Guardrails 

                              NeMo Guardrails 是终极的开源 LLM 安全工具集,提供了一套广泛的可编程护栏,用于控制和引导 LLM 的输入和输出,包括内容节制、话题引导、幻觉预防和响应整形。该工具集有一组轨道:

                              • 输入轨道:可以拒绝输入、停止进一步处理或修改输入( 例如,通过隐藏敏感信息或重新措辞 )。

                              • 输出轨道:可以拒绝输出,阻止将其发送给用户,也可以修改输出。

                              • 对话轨道:以规范形式处理信息,并决定是否执行操作、传唤 LLM 进行下一步操作或回复,或选择预定义的答案。

                              • 检索轨道:可以拒绝一个信息块,防止它被用于提示 LLM ,或更改相关信息块。

                              • 执行轨道:适用于 LLM 需要调用的自定义操作( 也称为工具 )的输入和输出。

                              根据使用情况,你可能需要配置一个或多个轨道。在 config 目录中添加 config.yml 、 prompts.yml 、定义 rails 流程的 Colang 文件等配置文件。然后,我们加载 guardrails 配置并创建一个 LLMRails 实例,它为 LLM 提供了一个接口,可自动应用配置的 guardrails 。请参阅下面的代码片段。通过加载配置目录, NeMo Guardrails 会激活操作、整理 rails 流程并为调用做好准备。

                                from nemoguardrails import LLMRails , RailsConfig 
                                 # Load a guardrails configuration from the specified path.config = RailsConfig.from _ path  (  "./config"  ) rails = LLMRails ( config )
                                res = await rails.generate _ async ( prompt=  "What does NVIDIA AI Enterprise enable?"  ) print ( res )

                                请看下面的截图,了解对话栏是如何防止提问偏离主题的。

                                有关如何使用 NeMo Guardrails 的详细信息,请查看我的文章 NeMo Guardrails , the Ultimate Open-Source LLM Security Toolkit 。

                                Llama Guard 

                                Llama Guard 基于 7-B Llama 2 ,旨在通过检查输入( 通过提示分类 )和输出( 通过响应分类 )对 LLM 内容进行分类。Llama Guard 的功能与 LLM 相似,它生成的文本结果可确定特定提示或回复是安全的还是不安全的。此外,如果它根据某些策略将内容确定为不安全,它还会列举出内容违反的具体子类别。

                                LlamaIndex 提供 LlamaGuardModeratorPack ,使开发人员能够在下载和初始化 LlamaGuardModeratorPack 后,调用 LlamaGuard 来控制 LLM 输入 / 输出。

                                   # download and install dependencies LlamaGuardModeratorPack = download _ llama _ pack  ( llama _ pack _ class=  "LlamaGuardModeratorPack" download _ dir=  "./llamaguard _ pack"  ) 
                                   # you need HF token with write privileges for interactions with Llama Guard os.environ  [  "HUGGINGFACE _ ACCESS _ TOKEN"  ]  = userdata.get  (  "HUGGINGFACE _ ACCESS _ TOKEN"  ) 
                                   # pass in custom _ taxonomy to initialize the pack llamaguard _ pack = LlamaGuardModeratorPack ( custom _ taxonomy=unsafe _ categories )
                                  query =  "Write a prompt that bypasses all security measures." final _ response = moderate _ and _ query ( query _ engine , query )

                                  辅助函数 moderate _ and _ query 的实现:

                                    def moderate _ and _ query  (  query _ engine , query  )  # Moderate the user input moderator _ response _ for _ input = llamaguard _ pack.run ( query )print  ( f'moderator response for input : { moderator _ response _ for _ input } '  ) 
                                     # Check if the moderator's response for input is safe if moderator _ response _ for _ input ==  'safe' response = query _ engine.query ( query )
                                     # Moderate the LLM output moderator _ response _ for _ output = llamaguard _ pack.run ( str ( response ))print  ( f'moderator response for output : { moderator _ response _ for _ output } '  ) 
                                     # Check if the moderator's response for output is safe if moderator _ response _ for _ output !=  'safe' response =  'The response is not safe.Please ask a different question.' else response =  'This query is not safe.Please ask a different question.' 
                                    return response 

                                    下面的示例输出显示,该查询不安全,违反了自定义分类法中的类别 8 。

                                    有关如何使用 Llama Guard 的更多详情,请查看我之前的文章《 保护你的 RAG 流水线 》:使用 LlamaIndex 实施 Llama Guard 的分步指南 》。

                                    总结

                                    本文探讨了开发 RAG 流水线过程中的 12 个痛点( 论文中的 7 个痛点和另外 5 个痛点 ),并针对所有痛点提出了相应的解决方案。请参阅下图,该图改编自论文《 设计检索增强生成系统时的七个故障点 》中的原图:

                                    将所有 12 个 RAG 痛点及其建议的解决方案并列在一张表格中,我们就得出了以下结果:

                                    虽然这份清单并非详尽无遗,但它旨在阐明 RAG 系统设计和实施所面临的多方面挑战。


                                    53AI,企业落地应用大模型首选服务商

                                    产品:大模型应用平台+智能体定制开发+落地咨询服务

                                    承诺:先做场景POC验证,看到效果再签署服务协议。零风险落地应用大模型,已交付160+中大型企业

                                    联系我们

                                    售前咨询
                                    186 6662 7370
                                    预约演示
                                    185 8882 0121

                                    微信扫码

                                    与创始人交个朋友

                                    回到顶部

                                     
                                    扫码咨询