链载Ai

标题: 总结了 13 个 顶级 RAG 技术 [打印本页]

作者: 链载Ai    时间: 昨天 22:26
标题: 总结了 13 个 顶级 RAG 技术

AI 能否大规模生成真正相关的答案?我们如何确保它理解复杂的多轮对话?我们如何防止它轻率地吐出错误的事实?这些都是现代 AI 系统面临的挑战,尤其是使用 RAG 构建的系统。RAG 将文档检索的强大功能与语言生成的流畅性相结合,使系统能够基于上下文感知、基于事实的响应来回答问题。虽然基本的 RAG 系统在处理简单任务时表现良好,但在处理复杂查询、幻听以及长时间交互中的上下文记忆时,它们往往会遇到问题。这时,高级 RAG 技术就派上用场了。


在本篇博文中,我们将探讨如何升级你的 RAG 流水线,从而增强堆栈的每个阶段:索引、检索和生成。我们将逐步介绍一些强大的方法(并附上实际代码),这些方法可以帮助你提升相关性、降低噪音并扩展系统性能——无论你是构建医疗助理、教育导师还是企业知识机器人。


基本 RAG 的不足之处是什么?


让我们看一下基本 RAG 框架:


图片

这个 RAG 系统架构展示了向量存储中块嵌入的基本存储方式。第一步是加载文档,然后使用各种分块技术对其进行拆分或分块,最后使用嵌入模型进行嵌入,以便 LLM 能够轻松理解。


这张图描绘了RAG的检索和生成步骤:用户提出一个问题,然后我们的系统通过搜索 Vector 库,根据该问题提取结果。检索到的内容连同问题一起传递给 LLM,LLM 提供结构化的输出。


基本的 RAG 系统有明显的局限性,尤其是在苛刻的情况下。


    utside;" class="list-paddingleft-1">
  • 幻觉:幻觉是一个主要问题。该模型创建的内容在事实上是错误的,或者没有源文档的支持。这会损害可靠性,尤其是在医学或法律等精确性至关重要的领域。

  • 缺乏领域特异性:标准 RAG 模型难以处理专业主题。如果不根据领域的具体细节调整检索和生成过程,系统可能会发现不相关或不准确的信息。

  • 复杂对话:基本的 RAG 系统难以处理复杂的查询或多轮对话。它们经常在交互过程中丢失上下文信息,导致答案不连贯或不完整。RAG 系统必须能够处理日益复杂的查询。


因此,我们将逐一介绍 RAG 堆栈的高级 RAG 技术,即索引、检索和生成。我们将讨论如何使用开源库和资源进行改进。无论你构建的是医疗聊天机器人、教育机器人还是其他应用程序,这些高级 RAG 技术都具有普遍适用性。它们将改进大多数 RAG 系统。


让我们从高级 RAG 技术开始吧!


索引和分块:构建坚实的基础


良好的索引对于任何 RAG 系统都至关重要。第一步涉及如何导入、拆分和存储数据。让我们探索索引数据的方法,重点介绍如何索引和分块文本以及使用元数据。


1. HNSW


Hierarchical Navigable Small Worlds (HNSW)是一种在大型数据集中查找相似项的有效算法。它使用基于图的结构化方法,帮助快速定位近似最近邻 (ANN) 。


    utside;" class="list-paddingleft-1">
  • 邻近图:HNSW 构建了一个图,其中每个点都连接到附近的点。这种结构可以实现高效的搜索。

  • 层次结构:该算法将点组织成多层。顶层连接较远的点,而较低层连接较近的点。这种设置加快了搜索过程。

  • 贪婪路由:HNSW 使用贪婪算法来寻找邻居。它从高阶点开始,然后移动到最近的邻居,直到达到局部最小值。这种方法减少了查找相似项目所需的时间。


HNSW如何运作?


HNSW 的工作包括几个关键部分:


  • 输入层:每个数据点表示为高维空间中的向量。
  • 图形构造:
    • 每次将一个节点添加到图中。
    • 每个节点根据概率函数被分配到某一层。该函数决定了节点被放置在更高层的可能性。
    • 该算法平衡了连接数和搜索速度。
  • 搜索过程:
    • 搜索从顶层的特定入口点开始。
    • 该算法每一步都会移动到最近的邻居。
    • 一旦达到局部最小值,它就会转移到下一个较低层并继续搜索,直到找到底层的最近点。
  • 参数:
    • M:连接到每个节点的邻居数量。
    • efConstruction:此参数影响算法在构建图形时考虑的邻居数量。
    • efSearch:此参数影响搜索过程,确定要评估多少个邻居。


HNSW 的设计使其能够快速准确地找到相似的项目。这使得它成为需要在大型数据集中高效搜索的任务的理想选择。


图片

该图描绘了一个简化的 HNSW 搜索:算法从“入口点”(蓝色)开始,将图导航至“查询向量”(黄色)。“最近邻”(条纹)是通过基于邻近度的边遍历来识别的。这说明了高效近似最近邻搜索的图导航核心概念。


体验 HNSW


请按照以下步骤使用 FAISS 实现分层可导航小世界 (HNSW) 算法。本指南包含示例输出,用于说明该过程。


步骤 1:设置 HNSW 参数


首先,定义 HNSW 索引的参数。需要指定向量的大小以及每个节点的邻居数量。


importfaissimportnumpyasnp#SetupHNSWparametersd=128#SizeofthevectorsM=32#Numberofneighborsforeachnodel


步骤 2:初始化 HNSW 索引


使用上面定义的参数创建 HNSW 索引。


#InitializetheHNSWindexindex=faiss.IndexHNSWFlat(d,M)


步骤 3:设置 efConstruction


在将数据添加到索引之前,请设置 efConstruction 参数。此参数控制算法在构建索引时考虑的邻居数量。


efConstruction=200#ExamplevalueforefConstructionindex.hnsw.efConstruction=efConstruction


步骤4:生成示例数据


在此示例中,生成要索引的随机数据。其中,“xb”表示要索引的数据集。


#Generaterandomdatasetofvectorsn=10000#Numberofvectorstoindexxb=np.random.random((n,d)).astype('float32')#Adddatatotheindexindex.add(xb)#Buildtheindex


步骤 5:设置 efSearch


建立索引后,设置 efSearch 参数。此参数影响搜索过程。


efSearch=100#ExamplevalueforefSearchindex.hnsw.efSearch=efSearch


步骤 6:执行搜索


现在,你可以搜索查询向量的最近邻。这里,“xq”表示查询向量。


#Generaterandomqueryvectorsnq=5#Numberofqueryvectorsxq=np.random.random((nq,d)).astype('float32')#Performasearchforthetopknearestneighborsk=5#Numberofnearestneighborstoretrievedistances,indices=index.search(xq,k)#Outputtheresultsprint("QueryVectors:\n",xq)print("\nNearestNeighborsIndices:\n",indices)print("\nNearestNeighborsDistances:\n",distances)


输出


查询向量:[[0.123456780.23456789...0.98765432][0.234567890.34567890...0.87654321][0.345678900.45678901...0.76543210][0.456789010.56789012...0.65432109][0.567890120.67890123...0.54321098]]最近邻索引:[[123456789101112][234567890123134][345678901234245][456789012345356][567890123456467]]最近邻距离:[[0.1230.2340.3450.4560.567][0.2340.3450.4560.5670.678][0.3450.4560.5670.6780.789][0.4560.5670.6780.7890.890][0.5670.6780.7890.8900.901]]


2. 语义分块


这种方法根据含义而非固定大小划分文本。每个块代表一段连贯的信息。我们计算句子嵌入之间的余弦距离。如果两个句子语义相似(低于阈值),则将它们归入同一块。这会根据内容的含义创建不同长度的块。


    utside;" class="list-paddingleft-1">
  • 优点:创建更连贯、更有意义的块,改善检索。

  • 缺点:需要更多计算(使用基于 BERT 的编码器)。


动手语义分块


fromlangchain_experimental.text_splitterimportSemanticChunkerfromlangchain_openai.embeddingsimportOpenAIEmbeddingstext_splitter=SemanticChunker(OpenAIEmbeddings())docs=text_splitter.create_documents([document])print(docs[0].page_content)


这段代码使用了 LangChain 的 SemanticChunker,它使用 OpenAI 嵌入将文档拆分为语义相关的块。它创建的文档块旨在捕获连贯的语义单元,而不是任意的文本片段。


3.基于语言模型的分块


这种先进的方法使用语言模型从文本中创建完整的语句。每个块在语义上都是完整的。语言模型(例如,一个拥有 70 亿个参数的模型)负责处理文本。它将文本分解成各自有意义的语句。然后,该模型将这些语句组合成块,在完整性和上下文之间取得平衡。这种方法计算量很大,但准确率很高。


    utside;" class="list-paddingleft-2">
  • 优点:适应文本的细微差别并创建高质量的块。

  • 缺点:计算成本高;可能需要针对特定用途进行微调。


基于语言模型的分块实践


asyncdefgenerate_contexts(document,chunks):asyncdefprocess_chunk(chunk):response=awaitclient.chat.completions.create(model="gpt-4o",messages=[{"role":"system","content":"Generateabriefcontextexplaininghowthischunkrelatestothefulldocument."},{"role":"user","content":f"<document>\n{document}\n</document>\nHereisthechunkwewanttosituatewithinthewholedocument\n<chunk>\n{chunk}\n</chunk>\nPleasegiveashortsuccinctcontexttosituatethischunkwithintheoveralldocumentforthepurposesofimprovingsearchretrievalofthechunk.Answeronlywiththesuccinctcontextandnothingelse."}],temperature=0.3,max_tokens=100)context=response.choices[0].message.contentreturnf"{context}{chunk}"#Processallchunksconcurrentlycontextual_chunks=awaitasyncio.gather(*[process_chunk(chunk)forchunkinchunks])returncontextual_chunks


此代码片段利用 LLM(可能是 OpenAI 的 DeepSeek,通过 client.chat.completions.create 调用)为文档的每个块生成上下文信息。它异步处理每个块,促使 LLM 解释该块与完整文档的关系。最后,它返回一个原始块列表,并在列表前面添加了生成的上下文,从而有效地丰富了这些块,从而改进了搜索检索。


4. 利用元数据:添加上下文


添加和过滤元数据


元数据提供额外的上下文信息,从而提高检索的准确性。通过添加日期、患者年龄和既往病史等元数据,你可以在搜索过程中过滤掉不相关的信息。过滤功能可以缩小搜索范围,提高检索效率和相关性。索引时,请将元数据与文本一起存储。


例如,医疗保健数据包括患者记录中的年龄、就诊日期和具体病情。使用这些元数据来筛选搜索结果,确保系统只检索相关信息。例如,如果查询与儿童相关,则过滤掉 18 岁以上患者的记录。这可以减少噪音并提高相关性。


例子


块#1


SourceMetadata:{'id':'doc:1c6f3e3f7ee14027bc856822871572dc:26e9aac7d5494208a56ff0c6cbbfda20','source':'https://plato.stanford.edu/entries/goedel/'}


源文本:


2.2.1TheFirstIncompletenessTheoremInhisLogicalJourney(Wang1996)HaoWangpublishedthefulltextofmaterialGödelhadwritten(atWang’srequest)abouthisdiscoveryoftheincompletenesstheorems.ThismaterialhadformedthebasisofWang’s“SomeFactsaboutKurtGödel,”andwasreadandapprovedbyGödel:


块#2


SourceMetadata:{'id':'doc:1c6f3e3f7ee14027bc856822871572dc:d15f62c453c64072b768e136080cb5ba','source':'https://plato.stanford.edu/entries/goedel/'}


源文本:


TheFirstIncompletenessTheoremprovidesacounterexampletocompletenessbyexhibitinganarithmeticstatementwhichisneitherprovablenorrefutableinPeanoarithmetic,thoughtrueinthestandardmodel.TheSecondIncompletenessTheoremshowsthattheconsistencyofarithmeticcannotbeprovedinarithmeticitself.ThusGödel’stheoremsdemonstratedtheinfeasibilityoftheHilbertprogram,ifitistobecharacterizedbythoseparticulardesiderata,consistencyandcompleteness.


在这里,我们可以看到元数据包含块的唯一 ID 和来源,这为块提供了更多上下文并有助于轻松检索。


5. 使用 GLiNER 生成元数据


你不会总是拥有大量的元数据,但使用像 GLiNER 这样的模型可以动态生成元数据!GLiNER 在摄取过程中标记和标记块以创建元数据。


执行


为每个块添加标签以供 GLiNER 识别。如果找到标签,它会对其进行标记。如果没有匹配的标签,则不会生成标签。 通常情况下效果良好,但对于小众数据集可能需要进行微调。这提高了检索准确率,但增加了一个处理步骤。GLiNER 可以解析传入的查询,并将其与元数据标签进行匹配以进行过滤。


GLiNER:使用双向 Transformer 进行命名实体识别的通用模型演示。


这些技术构建了强大的 RAG 系统,能够高效地从大型数据集中检索数据。分块和元数据的使用取决于数据集的具体需求和特性。


检索:找到正确的信息


现在,我们来关注一下 RAG 中的“R”。如何改进向量数据库的检索?这指的是检索与查询相关的所有文档。这大大提高了 LLM 生成高质量结果的几率。以下是一些技巧:


6.Hybrid Search混合搜索


结合向量搜索(查找语义含义)和关键词搜索(查找精确匹配)。混合搜索兼具两者的优势。在人工智能领域,许多术语都是特定的关键词:算法名称、技术术语、LLM (LLM)。单独的向量搜索可能会遗漏这些术语。关键词搜索可以确保这些重要术语得到考虑。结合两种方法可以创建更完整的检索流程。这些搜索同时运行。


使用加权系统对结果进行合并和排序。例如,使用 Weaviate,你可以调整 alpha 参数来平衡向量和关键词结果。这样就可以创建一个合并的排序列表。


    utside;" class="list-paddingleft-2">
  • 优点:平衡精度和召回率,提高检索质量。

  • 缺点:需要仔细调整重量。


动手混合搜索


fromlangchain_community.retrieversimportWeaviateHybridSearchRetrieverfromlangchain_core.documentsimportDocumentretriever=WeaviateHybridSearchRetriever(client=client,index_name="LangChain",text_key="text",attributes=[],create_schema_if_missing=True,)retriever.invoke("theethicalimplicationsofAI")


此代码初始化了一个 WeaviateHybridSearchRetriever,用于从 Weaviate 矢量数据库中检索文档。它将矢量搜索和关键字搜索结合到了 Weaviate 的混合检索功能中。最后,它执行了一个名为“the ethical implications of AI”的查询,并使用此混合方法检索相关文档。


7.查询重写


认识到人类查询可能并非数据库或语言模型的最佳选择。使用语言模型重写查询可以显著提高检索效果。


    utside;" class="list-paddingleft-1">
  1. 向量数据库重写:这将用户的初始查询转换为数据库友好的格式。例如,“什么是人工智能代理以及为什么它们是 2025 年的下一个大事件”可以转换为“人工智能代理是 2025 年的重大事件”。我们可以使用任何 LLM 来重写查询,以便它能够捕捉查询的重要方面。

  2. 语言模型的提示重写:这涉及自动创建提示以优化与语言模型的交互。这可以提高结果的质量和准确性。我们可以使用 DSPy 等框架或任何 LLM 来重写查询。这些重写的查询和提示确保搜索过程检索到相关文档,并有效地提示语言模型。


多查询检索


查询措辞的细微变化可能会导致检索结果不同。如果嵌入不能准确反映数据的含义,这个问题可能会更加突出。为了应对这些挑战,通常会采用快速工程或调优的方法,但这个过程可能非常耗时。


MultiQueryRetriever简化了这项任务。它使用大型语言模型 (LLM),基于单个用户输入从不同角度创建多个查询。对于每个生成的查询,它会检索一组相关文档。MultiQueryRetriever通过整合所有查询的独特结果, 提供了更广泛的潜在相关文档集。这种方法提高了找到有用信息的机会,而无需进行大量的手动调整。


fromlangchain_openaiimportChatOpenAIchatgpt=ChatOpenAI(model_name="gpt-4o",temperature=0)fromlangchain.retrievers.multi_queryimportMultiQueryRetriever#Setloggingforthequeriesimportloggingsimilarity_retriever3=chroma_db3.as_retriever(search_type="similarity",search_kwargs={"k":2})mq_retriever=MultiQueryRetriever.from_llm(retriever=similarity_retriever3,llm=chatgpt,include_original=True)logging.basicConfig()#sowecanseewhatqueriesaregeneratedbytheLLMlogging.getLogger("langchain.retrievers.multi_query").setLevel(logging.INFO)query="whatisthecapitalofIndia?"docs=mq_retriever.invoke(query)docs


此代码使用 LangChain 构建了一个多查询检索系统。它会生成输入查询(“what is the capital of India?”)的多个变体。然后,这些变体会通过相似性检索器查询 Chroma 向量数据库 (chroma_db3),旨在扩大搜索范围并捕获各种相关文档。MultiQueryRetriever 最终会聚合并返回检索到的文档。


输出


[Document(metadata={'article_id':'5117','title':'NewDelhi'},page_content='NewDelhi()isthecapitalofIndiaandaunionterritoryofthemegacityofDelhi.Ithasaveryoldhistoryandishometoseveralmonumentswherethecityisexpensivetolivein.IntraditionalIndiangeographyitfallsundertheNorthIndianzone.Thecityhasanareaofabout42.7\xa0km.NewDelhihasapopulationofabout9.4Millionpeople.'),Document(metadata={'article_id':'4062','title':'Kolkata'},page_content="Kolkata(spelledCalcuttabefore1January2001)isthecapitalcityoftheIndianstateofWestBengal.ItisthesecondlargestcityinIndiaafterMumbai.ItisontheeastbankoftheRiverHooghly.WhenitiscalledCalcutta,itincludesthesuburbs.ThismakesitthethirdlargestcityofIndia.Thisalsomakesittheworld's8thlargestmetropolitanareaasdefinedbytheUnitedNations.KolkataservedasthecapitalofIndiaduringtheBritishRajuntil1911.Kolkatawasoncethecenterofindustryandeducation.However,ithaswitnessedpoliticalviolenceandeconomicproblemssince1954.Since2000,Kolkatahasgrownduetoeconomicgrowth.LikeothermetropolitancitiesinIndia,Kolkatastruggleswithpoverty,pollutionandtrafficcongestion."),Document(metadata={'article_id':'22215','title':'StatesandunionterritoriesofIndia'},page_content='TheRepublicofIndiaisdividedintotwenty-eightStates,andeightunionterritoriesincludingtheNationalCapitalTerritory.')]


8. LLM基于提示的上下文压缩检索


上下文压缩有助于提高检索文档的相关性。这主要通过两种方式实现:


    utside;" class="list-paddingleft-1">
  1. 提取相关内容:删除检索到的文档中与查询无关的部分。这意味着只保留回答问题的部分。

  2. 过滤不相关文档:排除与查询无关的文档,而不改变文档本身的内容。


为了实现这一点,我们可以使用 LLMChainExtractor,它会审查最初返回的文档,并仅提取与查询相关的内容。它也可能删除完全不相关的文档。


以下是使用 LangChain 实现此目的的方法:


fromlangchain.retrieversimportContextualCompressionRetrieverfromlangchain.retrievers.document_compressorsimportLLMChainExtractorfromlangchain_openaiimportChatOpenAI#Initializethelanguagemodelchatgpt=ChatOpenAI(model_name="gpt-4o",temperature=0)#Setupasimilarityretrieversimilarity_retriever=chroma_db3.as_retriever(search_type="similarity",search_kwargs={"k":3})#Createtheextractortogetrelevantcontentcompressor=LLMChainExtractor.from_llm(llm=chatgpt)#Combinetheretrieverandtheextractorcompression_retriever=ContextualCompressionRetriever(base_compressor=compressor,base_retriever=similarity_retriever)#Examplequeryquery="WhatisthecapitalofIndia?"docs=compression_retriever.invoke(query)print(docs)


输出:


[Document(metadata={'article_id':'5117','title':'NewDelhi'},page_content='NewDelhiisthecapitalofIndiaandaunionterritoryofthemegacityofDelhi.')]


对于不同的查询:


query="WhatistheoldcapitalofIndia?"docs=compression_retriever.invoke(query)print(docs)


输出


[Document(metadata={'article_id':'4062','title':'Kolkata'},page_content='KolkataservedasthecapitalofIndiaduringtheBritishRajuntil1911.')]


LLMChainFilter 提供了一种更简单但有效的文档过滤方法。它使用 LLM 链来决定哪些文档需要保留、哪些文档需要丢弃,且不会改变文档的内容。


以下是实现过滤器的方法:


fromlangchain.retrievers.document_compressorsimportLLMChainFilter#Setupthefilter_filter=LLMChainFilter.from_llm(llm=chatgpt)#Combinetheretrieverandthefiltercompression_retriever=ContextualCompressionRetriever(base_compressor=_filter,base_retriever=similarity_retriever)#Examplequeryquery="WhatisthecapitalofIndia?"docs=compression_retriever.invoke(query)print(docs)


输出:


[Document(metadata={'article_id':'5117','title':'NewDelhi'},page_content='NewDelhiisthecapitalofIndiaandaunionterritoryofthemegacityofDelhi.')]


对于另一个查询:


query="WhatistheoldcapitalofIndia?"docs=compression_retriever.invoke(query)print(docs)


输出:


[Document(metadata={'article_id':'4062','title':'Kolkata'},page_content='KolkataservedasthecapitalofIndiaduringtheBritishRajuntil1911.')]


这些策略通过关注相关内容来帮助优化检索过程。“LLMChainExtractor”仅提取文档的必要部分,而“LLMChainFilter”则决定保留哪些文档。这两种方法都提高了检索信息的质量,使其与用户的查询更加相关。


9. 微调嵌入模型


预先训练好的嵌入模型是一个不错的开始。根据你的数据对这些模型进行微调可以显著提升检索效果。


选择合适的模型:对于医学等专业领域,请选择基于相关数据预训练的模型。例如,你可以使用 MedCPT 系列查询和文档编码器,这些编码器已基于 PubMed 搜索日志中的 2.55 亿个查询-文章对进行大规模预训练。


使用正样本对和负样本对进行微调:收集你自己的数据,并创建相似(正样本)和不相似(负样本)的样本对。对模型进行微调以理解这些差异。这有助于模型学习特定领域的关系,从而改进检索。


    utside;" class="list-paddingleft-2">
  • 优点:提高检索性能。

  • 缺点:需要精心创建的训练数据。


这些技术的组合构建了一个强大的检索系统。这提高了提供给 LLM 的对象的相关性,从而提升了生成质量。


生成:制作高质量的响应


最后,我们来讨论一下如何提高语言模型 (LLM) 的生成质量。目标是为 LLM 提供尽可能与提示相关的上下文。不相关的数据可能会引发幻觉。以下是一些提高生成质量的技巧:


10.自动剪切以删除不相关信息


Autocut 会过滤掉从数据库中检索到的不相关信息,从而防止LLM 被误导。


    utside;" class="list-paddingleft-1">
  • 检索和评分相似度:进行查询时,将检索具有相似度分数的多个对象。

  • 识别并剔除:使用相似度得分找到一个得分显著下降的临界点。排除超出此点的对象。这确保只向 LLM 提供最相关的信息。例如,如果你检索了六个对象,那么在第四个之后,得分可能会急剧下降。通过查看变化率,你可以确定要排除哪些对象。


fromlangchain_openaiimportOpenAIEmbeddingsfromlangchain_pineconeimportPineconeVectorStorefromtypingimportListfromlangchain_core.documentsimportDocumentfromlangchain_core.runnablesimportchainvectorstore=PineconeVectorStore.from_documents(docs,index_name="sample",embedding=OpenAIEmbeddings())@chaindefretriever(query:str):docs,scores=zip(*vectorstore.similarity_search_with_score(query))fordoc,scoreinzip(docs,scores):doc.metadata["score"]=scorereturndocsresult=retriever.invoke("dinosaur")result


此代码片段使用 LangChain 和 Pinecone 执行相似性搜索。它使用 OpenAI 嵌入来嵌入文档,将其存储在 Pinecone 向量存储中,并定义一个检索器函数。检索器搜索与给定查询(“dinosaur”)相似的文档,计算相似度分数,并将这些分数添加到文档元数据中,然后返回结果。


输出


[Document(page_content='Inhersecondbook,Dr.SimmonsdelvesdeeperintotheethicalconsiderationssurroundingAIdevelopmentanddeployment.Itisaneye-openingexaminationofthedilemmasfacedbydevelopers,policymakers,andsocietyatlarge.',metadata={}),Document(page_content='Acomprehensiveanalysisoftheevolutionofartificialintelligence,fromitsinceptiontoitsfutureprospects.Dr.Simmonscoversethicalconsiderations,potentials,andthreatsposedbyAI.',metadata={}),Document(page_content="Inhisfollow-upto'Symbiosis',Prof.Sterlingtakesalookatthesubtle,unnoticedpresenceandinfluenceofAIinoureverydaylives.ItrevealshowAIhasbecomewovenintoourroutines,oftenwithoutourexplicitrealization.",metadata={}),Document(page_content='rof.Sterlingexploresthepotentialforharmoniouscoexistencebetweenhumansandartificialintelligence.ThebookdiscusseshowAIcanbeintegratedintosocietyinabeneficialandnon-disruptivemanner.',metadata={})]


我们可以看到,它还给出了相似度分数,我们可以根据阈值进行截断。


11. 重新排序检索到的对象


重新排序使用更高级的模型来重新评估和排序最初检索到的对象。这可以提高最终检索集的质量。


    utside;" class="list-paddingleft-2">
  • 过度获取:最初检索的对象多于所需。

  • 应用排序模型:使用高延迟模型(通常是交叉编码器)重新评估相关性。该模型会逐对考虑查询和每个对象,以重新评估相似度。

  • 重新排序结果:根据新的评估结果,重新排序对象。将最相关的结果置于顶部。这可确保最相关的文档优先显示,从而改进提供给LLM (LLM) 的数据。


fromlangchain.retrieversimportContextualCompressionRetrieverfromlangchain.retrievers.document_compressorsimportFlashrankRerankfromlangchain_openaiimportChatOpenAIllm=ChatOpenAI(temperature=0)compressor=FlashrankRerank()compression_retriever=ContextualCompressionRetriever(base_compressor=compressor,base_retriever=retriever)compressed_docs=compression_retriever.invoke("WhatdidthepresidentsayaboutKetanjiJacksonBrown")print([doc.metadata["id"]fordocincompressed_docs])pretty_print_docs(compressed_docs)


此代码片段利用 ContextualCompressionRetriever 中的 FlashrankRerank 来提升检索到的文档的相关性。它根据查询“总统对 Ketanji Jackson Brown 有何评价”的相关性,对基础检索器(用 retriever 表示)获取的文档进行重新排序。最后,它会打印文档 ID 以及压缩后、重新排序后的文档。


输出


[0,5,3]Document1:OneofthemostseriousconstitutionalresponsibilitiesaPresidenthasisnominatingsomeonetoserveontheUnitedStatesSupremeCourt.AndIdidthat4daysago,whenInominatedCircuitCourtofAppealsJudgeKetanjiBrownJackson.Oneofournation’stoplegalminds,whowillcontinueJusticeBreyer’slegacyofexcellence.----------------------------------------------------------------------------------------------------Document2:HemettheUkrainianpeople.FromPresidentZelenskyytoeveryUkrainian,theirfearlessness,theircourage,theirdetermination,inspirestheworld.Groupsofcitizensblockingtankswiththeirbodies.Everyonefromstudentstoretireesteachersturnedsoldiersdefendingtheirhomeland.InthisstruggleasPresidentZelenskyysaidinhisspeechtotheEuropeanParliament“Lightwillwinoverdarkness.”TheUkrainianAmbassadortotheUnitedStatesisheretonight.----------------------------------------------------------------------------------------------------Document3:Andtonight,I’mannouncingthattheJusticeDepartmentwillnameachiefprosecutorforpandemicfraud.Bytheendofthisyear,thedeficitwillbedowntolessthanhalfwhatitwasbeforeItookoffice.Theonlypresidentevertocutthedeficitbymorethanonetrilliondollarsinasingleyear.Loweringyourcostsalsomeansdemandingmorecompetition.I’macapitalist,butcapitalismwithoutcompetitionisn’tcapitalism.It’sexploitation—anditdrivesupprices.


输出显示它根据相关性对检索到的块进行重新排序。


12. 微调LLM


使用特定领域数据对 LLM 进行微调可以显著提升其性能。例如,使用 Meditron 70B 这样的模型。这是针对医疗数据对 LLaMA 2 70b 进行微调的版本,同时使用了以下两种方法:


  • 无监督微调:继续对大量特定领域的文本进行预训练。

  • 监督微调:使用监督学习针对特定领域任务(例如医学多项选择题)进一步完善模型。这种专门的训练有助于模型在目标领域表现良好。在某些特定任务上,它的表现优于基础模型以及规模更大、专业性较低的模型(例如 GPT-3.5)。


微调

微调


此图表示针对特定任务示例进行微调的过程。这种方法允许开发人员指定所需的输出、鼓励某些行为,或更好地控制模型的响应。


13. 使用 RAFT:将语言模型适配到特定领域的 RAG


RAFT(检索增强微调)是一种改进大型语言模型 (LLM) 在特定领域工作方式的方法。它可以帮助这些模型利用文档中的相关信息更准确地回答问题。


  • 检索增强微调:RAFT 将微调与检索方法相结合。这使得模型在训练过程中能够从有用和不太有用的文档中学习。

  • 思路链推理:该模型生成的答案展现了其推理过程。这有助于它根据检索到的文档提供清晰准确的响应。

  • 动态文档处理:RAFT 训练模型查找和使用最相关的文档,同时忽略那些无助于回答问题的文档。


RAFT 的架构


RAFT 架构包含几个关键组件:


  • 输入层:模型输入一个问题(Q)和一组检索到的文档(D),其中包括相关文档和不相关文档。
  • 处理层:
    • 该模型分析输入以在文档中查找重要信息。
    • 它创建了一个引用相关文档的答案(A*)。
  • 输出层:模型根据相关文档产生最终答案,同时忽略不相关的文档。
  • 训练机制:在训练过程中,一些数据包含相关和不相关的文档,而其他数据仅包含不相关的文档。这种设置鼓励模型专注于上下文而不是记忆。
  • 评估:根据模型使用检索到的文档准确回答问题的能力来评估模型的性能。

通过采用这种架构,RAFT 增强了模型在特定领域的工作能力,并提供了一种生成准确且相关响应的可靠方法。


RAFT 的架构

RAFT 的架构


左上图展示了一种调整 LLM 的方法,使其能够从一组正向文档和干扰文档中读取解决方案。与标准 RAG 设置不同,标准 RAG 设置基于检索器输出进行训练,检索器输出是记忆和阅读的混合。测试时,所有方法均遵循标准 RAG 设置,并在上下文中提供前 k 个检索到的文档。


结论


改进 RAG 系统的检索和生成能力对于打造更优秀的 AI 应用至关重要。本文讨论的技术涵盖从低投入、高效率的方法(查询重写、重新排序)到更复杂的流程(嵌入和 LLM 微调)。最佳技术取决于你应用的具体需求和限制。先进的 RAG 技术,如果经过深思熟虑地应用,可以帮助开发人员构建更准确、更可靠、更具备情境感知能力的 AI 系统,从而处理复杂的信息需求







欢迎光临 链载Ai (https://www.lianzai.com/) Powered by Discuz! X3.5