自拍偷在线精品自拍偷,亚洲欧美中文日韩v在线观看不卡

深入剖析:如何利用 AI 智能體增強(qiáng)傳統(tǒng) RAG 系統(tǒng) 原創(chuàng) 精華

發(fā)布于 2025-3-26 10:21
瀏覽
0收藏

一、引言

在當(dāng)今的人工智能領(lǐng)域,生成式人工智能(Generative AI)正迅速發(fā)展,越來(lái)越多的企業(yè)希望利用定制數(shù)據(jù)構(gòu)建自己的生成式 AI 助手。檢索增強(qiáng)生成系統(tǒng)(Retrieval Augmented Generation systems,簡(jiǎn)稱 RAG 系統(tǒng))因其能夠避免對(duì)大語(yǔ)言模型(Large Language Models,LLMs)進(jìn)行昂貴的微調(diào)而迅速流行起來(lái)。RAG 系統(tǒng)的一個(gè)關(guān)鍵優(yōu)勢(shì)在于,它可以輕松集成企業(yè)自身的數(shù)據(jù),增強(qiáng)大語(yǔ)言模型的智能,并為用戶的問(wèn)題提供更具上下文的答案。

然而,傳統(tǒng)的 RAG 系統(tǒng)也面臨著一系列問(wèn)題,這些問(wèn)題可能導(dǎo)致其性能不佳,甚至給出錯(cuò)誤的答案。那么,有沒(méi)有一種方法可以改進(jìn)這些問(wèn)題呢?答案是肯定的。在本文中,我們將探討如何利用 AI 智能體(AI Agents)來(lái)增強(qiáng)傳統(tǒng) RAG 系統(tǒng)的能力,并解決其一些局限性。

二、傳統(tǒng) RAG 系統(tǒng)概述

(一)傳統(tǒng) RAG 系統(tǒng)架構(gòu)

傳統(tǒng)的 RAG 系統(tǒng)架構(gòu)通常由兩個(gè)主要步驟組成:數(shù)據(jù)處理和索引、檢索和響應(yīng)生成。

1.數(shù)據(jù)處理和索引:在這一步驟中,我們的重點(diǎn)是將定制的企業(yè)數(shù)據(jù)轉(zhuǎn)換為更易于處理的格式。具體來(lái)說(shuō),就是加載文本內(nèi)容以及其他工件(如圖表和圖像),將大文檔分割成較小的塊,使用嵌入模型將這些塊轉(zhuǎn)換為嵌入向量,然后將這些塊和嵌入向量存儲(chǔ)到向量數(shù)據(jù)庫(kù)中。

深入剖析:如何利用 AI 智能體增強(qiáng)傳統(tǒng) RAG 系統(tǒng)-AI.x社區(qū)

2.檢索和響應(yīng)生成:當(dāng)用戶提出問(wèn)題時(shí),這一步驟開(kāi)始。系統(tǒng)從向量數(shù)據(jù)庫(kù)中檢索與輸入問(wèn)題相似的相關(guān)文檔塊,然后將這些文檔塊與問(wèn)題一起發(fā)送給大語(yǔ)言模型(LLM),以生成類似人類的響應(yīng)。

深入剖析:如何利用 AI 智能體增強(qiáng)傳統(tǒng) RAG 系統(tǒng)-AI.x社區(qū)

這種兩步式工作流程在行業(yè)中被廣泛用于構(gòu)建傳統(tǒng)的 RAG 系統(tǒng),但它也存在一些局限性。

(二)傳統(tǒng) RAG 系統(tǒng)的局限性

傳統(tǒng) RAG 系統(tǒng)存在幾個(gè)明顯的局限性:

  1. 缺乏實(shí)時(shí)數(shù)據(jù):系統(tǒng)的表現(xiàn)依賴于向量數(shù)據(jù)庫(kù)中已有的數(shù)據(jù),對(duì)于實(shí)時(shí)發(fā)生的事件或數(shù)據(jù),無(wú)法及時(shí)獲取和處理。
  2. 檢索策略問(wèn)題:如果檢索策略不佳,可能會(huì)導(dǎo)致使用不相關(guān)的文檔來(lái)回答問(wèn)題,從而影響答案的準(zhǔn)確性。
  3. 大語(yǔ)言模型的局限性:LLM 可能會(huì)出現(xiàn)幻覺(jué)(hallucinations),即生成一些沒(méi)有事實(shí)依據(jù)的答案,或者無(wú)法回答某些問(wèn)題。

在本文中,我們將特別關(guān)注 RAG 系統(tǒng)無(wú)法訪問(wèn)實(shí)時(shí)數(shù)據(jù)的局限性,并確保檢索到的文檔塊確實(shí)與回答問(wèn)題相關(guān)。這樣可以使 RAG 系統(tǒng)能夠回答關(guān)于最近事件和實(shí)時(shí)數(shù)據(jù)的問(wèn)題,并減少出現(xiàn)幻覺(jué)的可能性。

三、糾正性 RAG 系統(tǒng)

糾正性 RAG 系統(tǒng)的靈感來(lái)自于論文《Corrective Retrieval Augmented Generation》(作者:Yan 等人)中提出的解決方案。其關(guān)鍵思想是像往常一樣從向量數(shù)據(jù)庫(kù)中檢索文檔塊,然后使用 LLM 檢查每個(gè)檢索到的文檔塊是否與輸入問(wèn)題相關(guān)。

如果所有檢索到的文檔塊都相關(guān),那么就像標(biāo)準(zhǔn)的 RAG 管道一樣,將其發(fā)送到 LLM 進(jìn)行正常的響應(yīng)生成。然而,如果某些檢索到的文檔與輸入問(wèn)題不相關(guān),我們會(huì)重新表述輸入查詢,在網(wǎng)絡(luò)上搜索與輸入問(wèn)題相關(guān)的新信息,然后將其發(fā)送到 LLM 以生成響應(yīng)。

深入剖析:如何利用 AI 智能體增強(qiáng)傳統(tǒng) RAG 系統(tǒng)-AI.x社區(qū)

這種方法的關(guān)鍵創(chuàng)新點(diǎn)包括在網(wǎng)絡(luò)上搜索,用實(shí)時(shí)數(shù)據(jù)擴(kuò)充向量數(shù)據(jù)庫(kù)中的靜態(tài)信息,以及檢查檢索到的文檔是否與輸入問(wèn)題相關(guān),這是簡(jiǎn)單的嵌入余弦相似度無(wú)法捕捉到的。

四、AI 智能體的興起

AI 智能體或智能 AI 系統(tǒng)在 2024 年有了顯著的發(fā)展,它使我們能夠構(gòu)建能夠推理、分析、交互并自動(dòng)采取行動(dòng)的生成式 AI 系統(tǒng)。智能 AI 的核心思想是構(gòu)建完全自主的系統(tǒng),能夠在最少的人工干預(yù)下理解和管理復(fù)雜的工作流程和任務(wù)。智能系統(tǒng)可以掌握細(xì)微的概念,設(shè)定并追求目標(biāo),通過(guò)任務(wù)進(jìn)行推理,并根據(jù)不斷變化的條件調(diào)整其行動(dòng)。這些系統(tǒng)可以由單個(gè)智能體或多個(gè)智能體組成。

深入剖析:如何利用 AI 智能體增強(qiáng)傳統(tǒng) RAG 系統(tǒng)-AI.x社區(qū)

我們可以使用各種框架來(lái)構(gòu)建智能 AI 系統(tǒng),包括 CrewAI、LangChain、LangGraph、AutoGen 等等。使用這些框架可以讓我們輕松開(kāi)發(fā)復(fù)雜的工作流程。需要記住的是,智能體基本上是一個(gè)或多個(gè)大語(yǔ)言模型,它們可以訪問(wèn)一組工具,并根據(jù)特定的基于提示的指令來(lái)回答用戶問(wèn)題。

在我們的實(shí)際實(shí)現(xiàn)中,我們將使用 LangGraph 來(lái)構(gòu)建我們的智能 RAG 系統(tǒng)。LangGraph 建立在 LangChain 之上,有助于創(chuàng)建循環(huán)圖,這對(duì)于開(kāi)發(fā)由 LLM 驅(qū)動(dòng)的 AI 智能體至關(guān)重要。它的接口受到廣泛使用的 NetworkX 庫(kù)的啟發(fā),能夠通過(guò)循環(huán)計(jì)算步驟協(xié)調(diào)和檢查點(diǎn)多個(gè)鏈(或參與者)。LangGraph 將智能體工作流程視為循環(huán)圖結(jié)構(gòu)。

深入剖析:如何利用 AI 智能體增強(qiáng)傳統(tǒng) RAG 系統(tǒng)-AI.x社區(qū)

LangGraph 智能體的主要組件包括:

  1. 節(jié)點(diǎn):函數(shù)或 LangChain 可運(yùn)行對(duì)象,如工具。
  2. :指定節(jié)點(diǎn)之間的有向路徑。
  3. 有狀態(tài)的圖:在通過(guò)節(jié)點(diǎn)處理數(shù)據(jù)時(shí)管理和更新?tīng)顟B(tài)對(duì)象。

LangGraph 利用這些來(lái)促進(jìn)具有狀態(tài)持久性的循環(huán) LLM 調(diào)用執(zhí)行,這是 AI 智能體經(jīng)常需要的。

五、智能糾正性 RAG 系統(tǒng)工作流程

智能糾正性 RAG 系統(tǒng)的工作流程包含了多個(gè)關(guān)鍵組件和執(zhí)行流程。該系統(tǒng)中有兩個(gè)主要的流程:

1.常規(guī) RAG 系統(tǒng)工作流程:用戶提出問(wèn)題,系統(tǒng)從向量數(shù)據(jù)庫(kù)中檢索上下文文檔。然后,我們引入了一個(gè)額外的步驟,即根據(jù)糾正性 RAG 論文的方法,使用 LLM 檢查所有檢索到的文檔是否與用戶問(wèn)題相關(guān)(在“評(píng)分”節(jié)點(diǎn));如果所有文檔都相關(guān),那么我們使用 LLM 生成響應(yīng)。

深入剖析:如何利用 AI 智能體增強(qiáng)傳統(tǒng) RAG 系統(tǒng)-AI.x社區(qū)

2.異常處理流程:如果從向量數(shù)據(jù)庫(kù)中檢索到的至少一個(gè)或多個(gè)上下文文檔與用戶問(wèn)題不相關(guān),那么我們利用 LLM 重寫用戶查詢,并對(duì)其進(jìn)行優(yōu)化以便在網(wǎng)絡(luò)上搜索。接下來(lái),我們利用網(wǎng)絡(luò)搜索工具使用這個(gè)重新表述的查詢?cè)诰W(wǎng)絡(luò)上搜索,并獲取一些新文檔。最后,我們將查詢和任何相關(guān)的上下文文檔(包括網(wǎng)絡(luò)搜索文檔)發(fā)送到 LLM 以生成響應(yīng)。

深入剖析:如何利用 AI 智能體增強(qiáng)傳統(tǒng) RAG 系統(tǒng)-AI.x社區(qū)

六、詳細(xì)的智能糾正性 RAG 系統(tǒng)架構(gòu)

我們從用戶查詢開(kāi)始,該查詢將發(fā)送到向量數(shù)據(jù)庫(kù)(我們將使用 Chroma),并檢索一些上下文文檔。如果用戶查詢基于最近的事件或超出我們向量數(shù)據(jù)庫(kù)中初始數(shù)據(jù)范圍的主題,那么有可能無(wú)法檢索到任何文檔。

接下來(lái),我們將用戶查詢和上下文文檔發(fā)送給 LLM,并使其充當(dāng)文檔評(píng)分器。它將根據(jù)每個(gè)上下文文檔在含義和上下文方面是否與用戶查詢相關(guān),將其評(píng)為“是”或“否”。

然后是決策節(jié)點(diǎn),這里有兩種可能的路徑:

  1. 所有文檔相關(guān)路徑:如果所有上下文文檔都與用戶查詢相關(guān),那么我們將進(jìn)入標(biāo)準(zhǔn)的 RAG 流程,即將文檔和查詢發(fā)送到 LLM,以生成作為用戶查詢答案的上下文響應(yīng)。
  2. 存在不相關(guān)文檔或無(wú)文檔路徑:如果至少有一個(gè)或多個(gè)上下文文檔與用戶查詢不相關(guān),或者對(duì)于給定的用戶查詢沒(méi)有上下文文檔,那么我們將用戶查詢發(fā)送給 LLM,并要求它重新表述用戶查詢,以優(yōu)化其在網(wǎng)絡(luò)上的搜索。

深入剖析:如何利用 AI 智能體增強(qiáng)傳統(tǒng) RAG 系統(tǒng)-AI.x社區(qū)

下一步是調(diào)用網(wǎng)絡(luò)搜索工具,在我們的實(shí)現(xiàn)中,我們將使用 Tavily Web Search API 工具在網(wǎng)絡(luò)上搜索并獲取相關(guān)信息作為上下文文檔,然后將它們添加到從向量數(shù)據(jù)庫(kù)中檢索到的任何相關(guān)上下文文檔列表中。

最后一步是通過(guò)相同的 RAG 流程,使用查詢和上下文文檔(包括從網(wǎng)絡(luò)檢索到的實(shí)時(shí)信息)生成響應(yīng)。

七、使用 LangGraph 進(jìn)行智能 RAG 系統(tǒng)的實(shí)踐實(shí)現(xiàn)

我們將使用 LangGraph 實(shí)現(xiàn)我們之前討論的智能 RAG 系統(tǒng)。我們將從 Wikipedia 加載一些文檔到我們的向量數(shù)據(jù)庫(kù)(Chroma 數(shù)據(jù)庫(kù))中,并使用 Tavily Search 工具進(jìn)行網(wǎng)絡(luò)搜索。與 LLM 的連接和提示將使用 LangChain 進(jìn)行,并且智能體將使用 LangGraph 構(gòu)建。對(duì)于我們的 LLM,我們將使用 ChatGPT GPT-4o,這是一個(gè)功能強(qiáng)大的 LLM,對(duì)工具調(diào)用具有原生支持。不過(guò),你也可以自由使用任何其他 LLM,包括開(kāi)源 LLM,建議使用經(jīng)過(guò)微調(diào)以進(jìn)行工具調(diào)用的強(qiáng)大 LLM 以獲得最佳性能。

(一)安裝依賴項(xiàng)

我們首先安裝必要的依賴項(xiàng),這些是我們構(gòu)建系統(tǒng)將使用的庫(kù):

!pip install langchain==0.2.0
!pip install langchain-openai==0.1.7
!pip install langchain-community==0.2.0
!pip install langgraph==0.1.1
!pip install langchain-chroma==0.1.1

(二)輸入 Open AI API 密鑰

我們使用 getpass() 函數(shù)輸入我們的 Open AI 密鑰,這樣我們就不會(huì)意外地在代碼中暴露我們的密鑰。

from getpass import getpass
OPENAI_KEY = getpass('Enter Open AI API Key: ')

(三)輸入 Tavily Search API 密鑰

同樣,我們使用 getpass() 函數(shù)輸入我們的 Tavily Search API 密鑰,并從指定位置獲取免費(fèi)的 API 密鑰。

TAVILY_API_KEY = getpass('Enter Tavily Search API Key: ')

(四)設(shè)置環(huán)境變量

接下來(lái),我們?cè)O(shè)置一些系統(tǒng)環(huán)境變量,這些變量將在稍后對(duì) LLM 進(jìn)行身份驗(yàn)證和搜索 API 時(shí)使用。

import os
os.environ['OPENAI_API_KEY'] = OPENAI_KEY
os.environ['TAVILY_API_KEY'] = TAVILY_API_KEY

(五)為 Wikipedia 數(shù)據(jù)構(gòu)建向量數(shù)據(jù)庫(kù)

我們從 Wikipedia 中選取一部分文檔來(lái)構(gòu)建用于檢索和搜索的向量數(shù)據(jù)庫(kù)。我們已經(jīng)從 Wikipedia 中提取了這些文檔并將它們存儲(chǔ)在一個(gè)存檔文件中。

Open AI 嵌入模型:LangChain 使我們能夠訪問(wèn) Open AI 嵌入模型,包括最新的模型:一個(gè)較小且高效的 text-embedding-3-small 模型和一個(gè)更大且功能更強(qiáng)大的 text-embedding-3-large 模型。我們需要一個(gè)嵌入模型,以便在將文檔塊存儲(chǔ)到向量數(shù)據(jù)庫(kù)之前將其轉(zhuǎn)換為嵌入向量。

from langchain_openai import OpenAIEmbeddings
openai_embed_model = OpenAIEmbeddings(model='text-embedding-3-small')

獲取 Wikipedia 數(shù)據(jù):我們已經(jīng)將 Wikipedia 文檔下載并存儲(chǔ)在 Google Drive 上的一個(gè)存檔文件中,你可以手動(dòng)下載,也可以使用以下代碼下載。如果無(wú)法使用代碼下載,可以從指定的 Google Drive 鏈接下載并手動(dòng)上傳到 Google Colab。

# 使用 Google Colab 下載
!gdown 1oWBnoxBZ1Mpeond8XDUSO6J9oAjcRDyW

加載和分塊文檔:我們現(xiàn)在將解壓數(shù)據(jù)存檔,加載文檔,將其分割和分塊為更易于管理的文檔塊,然后再進(jìn)行索引。

import gzip
import json
from langchain.docstore.document import Document
from langchain.text_splitter import RecursiveCharacterTextSplitter

wikipedia_filepath ='simplewiki-2020-11-01.jsonl.gz'
docs = []
with gzip.open(wikipedia_filepath, 'rt', encoding='utf8') as fIn:
    for line in fIn:
        data = json.loads(line.strip())
        docs.append({
           'metadata': {
                'title': data.get('title'),
                'article_id': data.get('id')
            },
            'data':''.join(data.get('paragraphs')[0:3]) 
        })
docs = [doc for doc in docs for x in ['india'] if x in doc['data'].lower().split()]
docs = [Document(page_cnotallow=doc['data'], metadata=doc['metadata']) for doc in docs]
splitter = RecursiveCharacterTextSplitter(chunk_size=2000, chunk_overlap=300)
chunked_docs = splitter.split_documents(docs)

創(chuàng)建向量數(shù)據(jù)庫(kù)并持久化到磁盤:我們初始化與 Chroma 向量數(shù)據(jù)庫(kù)客戶端的連接,并通過(guò)初始化 Chroma 客戶端并傳遞我們要保存數(shù)據(jù)的目錄來(lái)將數(shù)據(jù)保存到磁盤。我們還指定使用 Open AI 嵌入模型將每個(gè)文檔塊轉(zhuǎn)換為嵌入向量,并將文檔塊及其相應(yīng)的嵌入向量存儲(chǔ)在向量數(shù)據(jù)庫(kù)索引中。

from langchain_chroma import Chroma
chroma_db = Chroma.from_documents(documents=chunked_docs,
                                  collection_name='rag_wikipedia_db',
                                  embedding=openai_embed_model,
                                  collection_metadata={"hnsw:space": "cosine"},
                                  persist_directory="./wikipedia_db")

(六)設(shè)置向量數(shù)據(jù)庫(kù)檢索器

我們使用“帶閾值的相似性檢索”策略,該策略使用余弦相似性,并根據(jù)用戶輸入查詢檢索前 3 個(gè)最相似的文檔,同時(shí)引入一個(gè)截止值,以不返回任何低于特定相似性閾值(在這種情況下為 0.3)的文檔。

similarity_threshold_retriever = chroma_db.as_retriever(search_type="similarity_score_threshold",
                       search_kwargs={"k": 3,                                                                       
                       "score_threshold": 0.3})

我們可以通過(guò)一些示例查詢來(lái)測(cè)試我們的檢索器是否正常工作。

(七)創(chuàng)建查詢檢索評(píng)分器

我們使用 LLM(在我們的例子中是 GPT-4o)來(lái)判斷任何檢索到的文檔是否與給定問(wèn)題相關(guān),答案將是“是”或“否”。

from langchain_core.prompts import ChatPromptTemplate
from langchain_core.pydantic_v1 import BaseModel, Field
from langchain_openai import ChatOpenAI

class GradeDocuments(BaseModel):
    """Binary score for relevance check on retrieved documents."""
    binary_score: str = Field(
        descriptinotallow="Documents are relevant to the question, 'yes' or 'no'"
    )

llm = ChatOpenAI(model="gpt-4o", temperature=0)
structured_llm_grader = llm.with_structured_output(GradeDocuments)

SYS_PROMPT = """You are an expert grader assessing relevance of a retrieved document to a user question.
                Follow these instructions for grading:
                  - If the document contains keyword(s) or semantic meaning related to the question, grade it as relevant.
                  - Your grade should be either 'yes' or 'no' to indicate whether the document is relevant to the question or not."""

grade_prompt = ChatPromptTemplate.from_messages(
    [
        ("system", SYS_PROMPT),
        ("human", """Retrieved document:
                     {document}
                     User question:
                     {question}
                  """),
    ]
)

doc_grader = (grade_prompt | structured_llm_grader)

我們可以通過(guò)一些示例用戶查詢來(lái)測(cè)試這個(gè)評(píng)分器,看看從向量數(shù)據(jù)庫(kù)中檢索到的上下文文檔的相關(guān)性如何。

(八)構(gòu)建問(wèn)答 RAG 鏈

我們將檢索器連接到 LLM(在我們的例子中是 GPT-4o),并構(gòu)建我們的問(wèn)答 RAG 鏈。這將是我們的傳統(tǒng) RAG 系統(tǒng),我們稍后將其與 AI 智能體集成。

from langchain_core.prompts import ChatPromptTemplate
from langchain_openai import ChatOpenAI
from langchain_core.runnables import RunnablePassthrough, RunnableLambda
from langchain_core.output_parsers import StrOutputParser
from operator import itemgetter

prompt = """You are an assistant for question-answering tasks.
            Use the following pieces of retrieved context to answer the question.
            If no context is present or if you don't know the answer, just say that you don't know the answer.
            Do not make up the answer unless it is there in the provided context.
            Give a detailed answer and to the point answer with regard to the question.
            Question:
            {question}
            Context:
            {context}
            Answer:
         """
prompt_template = ChatPromptTemplate.from_template(prompt)

chatgpt = ChatOpenAI(model_name='gpt-4o', temperature=0)

def format_docs(docs):
    return"\n\n".join(doc.page_content for doc in docs)

qa_rag_chain = (
    {
        "context": (itemgetter('context') | RunnableLambda(format_docs)),
        "question": itemgetter('question')
    }
    |
    prompt_template
    |
    chatgpt
    |
    StrOutputParser()
)

我們可以通過(guò)一些查詢來(lái)測(cè)試我們的傳統(tǒng) RAG 系統(tǒng)。

(九)創(chuàng)建查詢重寫器

我們構(gòu)建一個(gè)查詢重寫器,它將使用 LLM(在我們的例子中是 GPT-4o)將輸入的用戶查詢重寫為更適合網(wǎng)絡(luò)搜索的更好版本。這將幫助我們從網(wǎng)絡(luò)上為我們的查詢獲取更好的上下文信息。

llm = ChatOpenAI(model="gpt-4o", temperature=0)

SYS_PROMPT = """Act as a question re-writer and perform the following task:
                 - Convert the following input question to a better version that is optimized for web search.
                 - When re-writing, look at the input question and try to reason about the underlying semantic intent / meaning.
             """
re_write_prompt = ChatPromptTemplate.from_messages(
    [
        ("system", SYS_PROMPT),
        ("human", """Here is the initial question:
                     {question}
                     Formulate an improved question.
                  """,
        ),
    ]
)

question_rewriter = (re_write_prompt
                        |
                       llm
                        |
                     StrOutputParser())

我們可以用一個(gè)示例問(wèn)題來(lái)測(cè)試查詢重寫器,看看它是如何工作的:

query = "who won the champions league in 2024?"
question_rewriter.invoke({"question": query})

輸出結(jié)果可能類似:

Who was the winner of the 2024 UEFA Champions League?

可以看到,查詢重寫器將原始問(wèn)題優(yōu)化為更適合網(wǎng)絡(luò)搜索的形式。

(十)加載網(wǎng)絡(luò)搜索工具

我們將使用 Tavily API 進(jìn)行網(wǎng)絡(luò)搜索,因此要建立與該 API 的連接。在搜索時(shí),我們將使用前 3 個(gè)搜索結(jié)果作為額外的上下文信息,當(dāng)然你也可以自由加載更多的搜索結(jié)果。

from langchain_community.tools.tavily_search import TavilySearchResults
tv_search = TavilySearchResults(max_results=3, search_depth='advanced',max_tokens=10000)

(十一)構(gòu)建智能 RAG 組件

圖狀態(tài)(Graph State):這用于存儲(chǔ)和表示智能體圖在遍歷各個(gè)節(jié)點(diǎn)時(shí)的狀態(tài)。它會(huì)存儲(chǔ)和跟蹤用戶查詢、一個(gè)指示是否需要進(jìn)行網(wǎng)絡(luò)搜索的標(biāo)志變量、一系列上下文文檔(從向量數(shù)據(jù)庫(kù)和/或網(wǎng)絡(luò)搜索中檢索到的)以及由 LLM 生成的響應(yīng)。

from typing import List
from typing_extensions import TypedDict


class GraphState(TypedDict):
    """
    Represents the state of our graph.
    Attributes:
        question: question
        generation: LLM response generation
        web_search_needed: flag of whether to add web search - yes or no
        documents: list of context documents
    """
    question: str
    generation: str
    web_search_needed: str
    documents: List[str]

從向量數(shù)據(jù)庫(kù)檢索的函數(shù)(Retrieve function for retrieval from Vector DB):這個(gè)函數(shù)用于通過(guò)我們之前構(gòu)建的檢索器從向量數(shù)據(jù)庫(kù)中獲取相關(guān)的上下文文檔。記住,由于它將成為智能體圖中的一個(gè)節(jié)點(diǎn),之后我們將從圖狀態(tài)中獲取用戶問(wèn)題,然后將其傳遞給檢索器,以從向量數(shù)據(jù)庫(kù)中獲取相關(guān)的上下文文檔。

def retrieve(state):
    """
    Retrieve documents
    Args:
        state (dict): The current graph state
    Returns:
        state (dict): New key added to state, documents - that contains retrieved context documents
    """
    print("---RETRIEVAL FROM VECTOR DB---")
    question = state["question"]
    # Retrieval
    documents = similarity_threshold_retriever.invoke(question)
    return {"documents": documents, "question": question}

文檔評(píng)分(Grade documents):這個(gè)函數(shù)用于使用 LLM 評(píng)分器來(lái)確定檢索到的文檔是否與問(wèn)題相關(guān)。如果至少有一個(gè)文檔在上下文上不相關(guān),或者沒(méi)有檢索到上下文文檔,它會(huì)將??web_search_needed?? 標(biāo)志設(shè)置為 “Yes”。否則,如果所有文檔在上下文上都與給定的用戶查詢相關(guān),它會(huì)將該標(biāo)志設(shè)置為 “No”。它還會(huì)更新?tīng)顟B(tài)圖,確保上下文文檔僅包含相關(guān)文檔。

def grade_documents(state):
    """
    Determines whether the retrieved documents are relevant to the question
    by using an LLM Grader.
    If any document are not relevant to question or documents are empty - Web Search needs to be done
    If all documents are relevant to question - Web Search is not needed
    Helps filtering out irrelevant documents
    Args:
        state (dict): The current graph state
    Returns:
        state (dict): Updates documents key with only filtered relevant documents
    """
    print("---CHECK DOCUMENT RELEVANCE TO QUESTION---")
    question = state["question"]
    documents = state["documents"]
    # Score each doc
    filtered_docs = []
    web_search_needed = "No"
    if documents:
        for d in documents:
            score = doc_grader.invoke(
                {"question": question, "document": d.page_content}
            )
            grade = score.binary_score
            if grade == "yes":
                print("---GRADE: DOCUMENT RELEVANT---")
                filtered_docs.append(d)
            else:
                print("---GRADE: DOCUMENT NOT RELEVANT---")
                web_search_needed = "Yes"
                continue
    else:
        print("---NO DOCUMENTS RETRIEVED---")
        web_search_needed = "Yes"
    return {"documents": filtered_docs, "question": question,
            "web_search_needed": web_search_needed}

查詢重寫(Rewrite query):這個(gè)函數(shù)用于使用 LLM 重寫輸入查詢,以生成一個(gè)更適合網(wǎng)絡(luò)搜索的優(yōu)化問(wèn)題。它還會(huì)更新?tīng)顟B(tài)圖中的查詢,以便我們即將創(chuàng)建的智能體圖中的其他節(jié)點(diǎn)可以訪問(wèn)它。

def rewrite_query(state):
    """
    Rewrite the query to produce a better question.
    Args:
        state (dict): The current graph state
    Returns:
        state (dict): Updates question key with a re-phrased or re-written question
    """
    print("---REWRITE QUERY---")
    question = state["question"]
    documents = state["documents"]
    # Re-write question
    better_question = question_rewriter.invoke({"question": question})
    return {"documents": documents, "question": better_question}

網(wǎng)絡(luò)搜索(Web Search):這個(gè)函數(shù)用于使用網(wǎng)絡(luò)搜索工具針對(duì)給定的查詢?cè)诰W(wǎng)絡(luò)上進(jìn)行搜索,并從網(wǎng)絡(luò)中檢索一些信息,這些信息可以在我們的 RAG 系統(tǒng)中用作額外的上下文文檔。正如前面所討論的,我們將在系統(tǒng)中使用 Tavily Search API 工具。這個(gè)函數(shù)還會(huì)更新?tīng)顟B(tài)圖,特別是上下文文檔列表,添加從網(wǎng)絡(luò)上為重新表述的用戶查詢檢索到的新文檔。

from langchain.schema import Document


def web_search(state):
    """
    Web search based on the re-written question.
    Args:
        state (dict): The current graph state
    Returns:
        state (dict): Updates documents key with appended web results
    """
    print("---WEB SEARCH---")
    question = state["question"]
    documents = state["documents"]
    # Web search
    docs = tv_search.invoke(question)
    web_results = "\n\n".join([d["content"] for d in docs])
    web_results = Document(page_cnotallow=web_results)
    documents.append(web_results)
    return {"documents": documents, "question": question}

生成答案(Generate Answer):這是 RAG 系統(tǒng)中從查詢和上下文文檔生成標(biāo)準(zhǔn) LLM 響應(yīng)的函數(shù)。我們還會(huì)更新?tīng)顟B(tài)圖中的??generation?? 字段,以便在智能體圖中的任何時(shí)候都可以訪問(wèn)它,并根據(jù)需要將響應(yīng)輸出給用戶。

def generate_answer(state):
    """
    Generate answer from context document using LLM
    Args:
        state (dict): The current graph state
    Returns:
        state (dict): New key added to state, generation, that contains LLM generation
    """
    print("---GENERATE ANSWER---")
    question = state["question"]
    documents = state["documents"]
    # RAG generation
    generation = qa_rag_chain.invoke({"context": documents, "question": question})
    return {"documents": documents, "question": question,
            "generation": generation}

決定生成(Decide to Generate):這個(gè)函數(shù)用作條件函數(shù),從智能體圖狀態(tài)中檢查??web_search_needed?? 標(biāo)志,并決定是進(jìn)行網(wǎng)絡(luò)搜索還是生成響應(yīng)。它將返回要調(diào)用的函數(shù)名稱。如果需要進(jìn)行網(wǎng)絡(luò)搜索,系統(tǒng)將返回??rewrite_query?? 字符串,促使我們的智能 RAG 系統(tǒng)遵循查詢重寫、搜索和響應(yīng)生成的流程。如果不需要進(jìn)行網(wǎng)絡(luò)搜索,該函數(shù)將返回??generate_answer?? 字符串,使我們的 RAG 系統(tǒng)進(jìn)入從給定上下文文檔和查詢生成響應(yīng)的常規(guī)流程。你將在我們智能體圖的條件節(jié)點(diǎn)中使用這個(gè)函數(shù),根據(jù)兩種可能的路徑將流程路由到正確的函數(shù)。

def decide_to_generate(state):
    """
    Determines whether to generate an answer, or re-generate a question.
    Args:
        state (dict): The current graph state
    Returns:
        str: Binary decision for next node to call
    """
    print("---ASSESS GRADED DOCUMENTS---")
    web_search_needed = state["web_search_needed"]
    if web_search_needed == "Yes":
        # All documents have been filtered check_relevance
        # We will re-generate a new query
        print("---DECISION: SOME or ALL DOCUMENTS ARE NOT RELEVANT TO QUESTION, REWRITE QUERY---")
        return "rewrite_query"
    else:
        # We have relevant documents, so generate answer
        print("---DECISION: GENERATE RESPONSE---")
        return "generate_answer"

(十二)使用 LangGraph 構(gòu)建智能體圖

我們使用 LangGraph 并根據(jù)上一節(jié)實(shí)現(xiàn)的函數(shù)將智能體構(gòu)建為一個(gè)圖,按照我們的智能 RAG 系統(tǒng)架構(gòu)將它們放入相關(guān)節(jié)點(diǎn),并根據(jù)定義的工作流程用相關(guān)邊連接它們。

from langgraph.graph import END, StateGraph
agentic_rag = StateGraph(GraphState)
# Define the nodes
agentic_rag.add_node("retrieve", retrieve)  # retrieve
agentic_rag.add_node("grade_documents", grade_documents)  # grade documents
agentic_rag.add_node("rewrite_query", rewrite_query)  # transform_query
agentic_rag.add_node("web_search", web_search)  # web search
agentic_rag.add_node("generate_answer", generate_answer)  # generate answer
# Build graph
agentic_rag.set_entry_point("retrieve")
agentic_rag.add_edge("retrieve", "grade_documents")
agentic_rag.add_conditional_edges(
    "grade_documents",
    decide_to_generate,
    {"rewrite_query": "rewrite_query", "generate_answer": "generate_answer"},
)
agentic_rag.add_edge("rewrite_query", "web_search")
agentic_rag.add_edge("web_search", "generate_answer")
agentic_rag.add_edge("generate_answer", END)
# Compile
agentic_rag = agentic_rag.compile()

我們可以使用以下代碼可視化我們的智能 RAG 系統(tǒng)工作流程:

from IPython.display import Image, display, Markdown
display(Image(agentic_rag.get_graph().draw_mermaid_png()))

深入剖析:如何利用 AI 智能體增強(qiáng)傳統(tǒng) RAG 系統(tǒng)-AI.x社區(qū)

(十三)測(cè)試我們的智能 RAG 系統(tǒng)

最后,我們準(zhǔn)備在一些用戶查詢上實(shí)時(shí)測(cè)試我們的智能 RAG 系統(tǒng)!由于我們?cè)趫D節(jié)點(diǎn)的相關(guān)函數(shù)中放置了打印語(yǔ)句,因此在圖執(zhí)行時(shí)我們可以看到它們的打印輸出。

場(chǎng)景一:查詢印度的首都

query = "what is the capital of India?"
response = agentic_rag.invoke({"question": query})

輸出如下:

---RETRIEVAL FROM VECTOR DB---
---CHECK DOCUMENT RELEVANCE TO QUESTION---
---GRADE: DOCUMENT RELEVANT---
---GRADE: DOCUMENT NOT RELEVANT---
---GRADE: DOCUMENT NOT RELEVANT---
---ASSESS GRADED DOCUMENTS---
---DECISION: SOME or ALL DOCUMENTS ARE NOT RELEVANT TO QUESTION, REWRITE QUERY---
---REWRITE QUERY---
---WEB SEARCH---
---GENERATE ANSWER—

可以看到,從向量數(shù)據(jù)庫(kù)中檢索到的一些文檔不相關(guān),因此它成功地從網(wǎng)絡(luò)上檢索了上下文信息并生成了響應(yīng)。我們現(xiàn)在可以查看生成的響應(yīng):

display(Markdown(response['generation']))

輸出:

The capital city of India is New Delhi. It is a union territory within the
 larger metropolitan area of Delhi and is situated in the north-central part
 of the country on the west bank of the Yamuna River. New Delhi was formally
 dedicated as the capital in 1931 and has a population of about 9.4 million
 people.

場(chǎng)景二:查詢 2024 年歐冠冠軍

query = "who won the champions league in 2024?"
response = agentic_rag.invoke({"question": query})

輸出:

---RETRIEVAL FROM VECTOR DB---
---CHECK DOCUMENT RELEVANCE TO QUESTION---
---GRADE: DOCUMENT NOT RELEVANT---
---ASSESS GRADED DOCUMENTS---
---DECISION: SOME or ALL DOCUMENTS ARE NOT RELEVANT TO QUESTION, REWRITE QUERY---
---REWRITE QUERY---
---WEB SEARCH---
---GENERATE ANSWER---

系統(tǒng)似乎按預(yù)期工作,由于沒(méi)有上下文文檔,它使用網(wǎng)絡(luò)搜索工具從網(wǎng)絡(luò)上檢索新信息來(lái)生成對(duì)我們查詢的響應(yīng)。我們現(xiàn)在可以查看響應(yīng):

display(Markdown(response['generation']))

輸出:

The winner of the 2024 UEFA Champions League was Real Madrid. They secured
 victory in the final against Borussia Dortmund with goals from Dani Carvajal
 and Vinicius Junior.

場(chǎng)景三:查詢關(guān)于印度的信息

query = "Tell me about India"
response = agentic_rag.invoke({"question": query})

輸出:

---RETRIEVAL FROM VECTOR DB---
---CHECK DOCUMENT RELEVANCE TO QUESTION---
---GRADE: DOCUMENT RELEVANT---
---GRADE: DOCUMENT RELEVANT---
---GRADE: DOCUMENT RELEVANT---
---ASSESS GRADED DOCUMENTS---
---DECISION: GENERATE RESPONSE---
---GENERATE ANSWER—

我們的智能 RAG 系統(tǒng)運(yùn)行良好,在這種情況下,由于所有檢索到的文檔都與回答用戶問(wèn)題相關(guān),所以它沒(méi)有進(jìn)行網(wǎng)絡(luò)搜索。我們現(xiàn)在可以查看響應(yīng):

display(Markdown(response['generation']))

輸出:

India is a country located in Asia, specifically at the center of South Asia.
 It is the seventh largest country in the world by area and the largest in
 South Asia. . . . . . .
 

India has a rich and diverse history that spans thousands of years,
 encompassing various languages, cultures, periods, and dynasties. The
 civilization began in the Indus Valley, . . . . . .

八、結(jié)論

在本指南中,我們深入了解了傳統(tǒng) RAG 系統(tǒng)當(dāng)前面臨的挑戰(zhàn)、AI 智能體的作用和重要性,以及智能 RAG 系統(tǒng)如何應(yīng)對(duì)其中的一些挑戰(zhàn)。我們?cè)敿?xì)討論了受《Corrective Retrieval Augmented Generation》論文啟發(fā)的智能糾正性 RAG 系統(tǒng)的詳細(xì)系統(tǒng)架構(gòu)和工作流程。最后但同樣重要的是,我們使用 LangGraph 實(shí)現(xiàn)了這個(gè)智能 RAG 系統(tǒng),并在各種場(chǎng)景下進(jìn)行了測(cè)試。你可以通過(guò)這個(gè) Colab 筆記本輕松訪問(wèn)代碼,并嘗試通過(guò)添加更多功能(如額外的幻覺(jué)檢查等)來(lái)改進(jìn)這個(gè)系統(tǒng)。

如果你想深入學(xué)習(xí)如何構(gòu)建這樣的智能 AI 系統(tǒng),可以參加 GenAI Pinnacle Program。在這里,你將通過(guò)與生成式 AI 專家的一對(duì)一指導(dǎo)、超過(guò) 200 小時(shí)的強(qiáng)化學(xué)習(xí)的高級(jí)課程以及對(duì) 26 多種 GenAI 工具和庫(kù)的掌握,徹底革新你的 AI 學(xué)習(xí)和開(kāi)發(fā)之旅。提升你的技能,成為 AI 領(lǐng)域的領(lǐng)導(dǎo)者。

希望本文能為你在 RAG 系統(tǒng)和 AI 智能體的探索中提供有價(jià)值的參考,讓我們一起期待在人工智能領(lǐng)域不斷創(chuàng)新和突破,構(gòu)建更智能、更高效的系統(tǒng),為各個(gè)行業(yè)帶來(lái)變革性的影響 。無(wú)論是企業(yè)應(yīng)用場(chǎng)景,還是學(xué)術(shù)研究方向,對(duì)這些技術(shù)的深入理解和應(yīng)用都將為我們打開(kāi)新的大門,創(chuàng)造更多可能。


本文轉(zhuǎn)載自公眾號(hào)Halo咯咯    作者:基咯咯

原文鏈接:??https://mp.weixin.qq.com/s/BnnKDkm14Js01ULgK_vcKQ??

?著作權(quán)歸作者所有,如需轉(zhuǎn)載,請(qǐng)注明出處,否則將追究法律責(zé)任
標(biāo)簽
收藏
回復(fù)
舉報(bào)
回復(fù)
相關(guān)推薦