分享方式:


Azure AI 搜尋服務中的擷取擴增生成 (RAG)

擷取擴增生成 (RAG) 是一種架構,可藉由新增提供基礎資料的資訊擷取系統,來增強 ChatGPT 等大型語言模型 (LLM) 的功能。 新增資訊擷取系統可讓您控制 LLM 在制訂回應時所使用的基礎資料。 針對企業解決方案,RAG 架構意味著,如果您已針對該內容內嵌模型,您可以將生成式 AI 限制到源於向量化文件和影像以及其他資料格式的企業內容

使用的資訊擷取系統的決策相當關鍵,因為它會決定 LLM 的輸入。 資訊擷取系統應該提供:

  • 編製索引策略可以按照您需要的頻率大規模載入和重新整理您的所有內容。

  • 查詢功能和相關性微調。 系統會傳回相關的結果,格式為符合 LLM 輸入之權杖長度需求所需的簡短形式格式。

  • 資料和作業的安全性、全域觸達及可靠性。

  • 與用於編製索引的內嵌模型整合,以及用於擷取的聊天模型或語言理解模型。

Azure AI 搜尋服務是 RAG 架構中經過驗證的資訊擷取解決方案。 其提供編製索引和查詢功能,以及 Azure 雲端的基礎結構和安全性。 透過程式碼和其他元件,您可以設計完整的 RAG 解決方案,其中包含透過專屬內容產生 AI 的所有元素。

注意

不熟悉副手和 RAG 概念嗎? 觀看向量搜尋及 Generative AI 應用程式的最先進擷取狀態

Microsoft 有數個內建實作,可用來在 RAG 解決方案中使用 Azure AI 搜尋服務。

策展的方法可讓您輕鬆地開始使用,但為了更充分掌控架構,您需要自訂解決方案。 這些範本會在下列專案中建立端對端解決方案:

本文的其餘部分將探討 Azure AI 搜尋服務如何融入自訂 RAG 解決方案。

模式的高階摘要如下所示:

  • 從使用者問題或要求開始 (提示)。
  • 將它傳送至 Azure AI 搜尋服務以尋找相關資訊。
  • 將排名最高的搜尋結果傳送至 LLM。
  • 使用 LLM 的自然語言理解和推理功能來產生初始提示的回應。

Azure AI 搜尋服務提供 LLM 提示字元的輸入,但不會定型模型。 在 RAG 架構中,沒有額外的定型。 LLM 會使用公用資料預先定型,但會產生由擷取程式的資訊所增強的回應。

包含 Azure AI 搜尋服務的 RAG 模式具有下圖所示的元素。

使用搜尋和 ChatGPT 擷取資訊的結構圖表。

  • 適用於使用者體驗的應用程式 UX (Web 應用程式)
  • 應用程式伺服器或協調器 (整合和協調層)
  • Azure AI 搜尋服務 (資訊擷取系統)
  • Azure OpenAI (適用於生成式 AI 的 LLM)

Web 應用程式提供使用者體驗、提供簡報、內容及使用者互動。 使用者的問題或提示從這裏開始。 輸入會透過整合層,先移至資訊擷取以取得搜尋結果,但也移至 LLM 來設定內容和意圖。

應用程式伺服器或協調器是整合程式碼,可協調資訊擷取與 LLM 之間的交接。 其中一個選項是使用 LangChain 來協調工作流程。 LangChain 與 Azure AI 搜尋服務整合,可讓您更輕鬆地將 Azure AI 搜尋服務納入工作流程中作為擷取器語意核心是另一個選項。

資訊擷取系統提供可搜尋的索引、查詢邏輯及承載 (查詢回應)。 搜尋索引可以包含向量或非向量內容。 雖然大部分的範例和示範都包含向量欄位,但並非必要的。 查詢是使用 Azure AI 搜尋服務中的現有搜尋引擎來執行,其可以處理關鍵字 (或字詞) 和向量查詢。 系統會根據您定義的結構描述,預先建立索引,並使用您從檔案、資料庫或儲存體來源的內容載入。

LLM 會收到原始提示,以及來自 Azure AI 搜尋服務的結果。 LLM 會分析結果並制訂回應。 如果 LLM 是 ChatGPT,則使用者互動可能是相互聊天。 如果您使用 Davinci,提示可能是完整撰寫的答案。 Azure 解決方案最有可能使用 Azure OpenAI,但此特定服務沒有硬性相依性。

Azure AI 搜尋不會提供提示流程或聊天保留的原生 LLM 整合,因此您必須撰寫可處理協調流程和狀態的程式碼。 您可以檢閱示範來源 (Azure-Samples/azure-search-openai-demo),以取得完整解決方案所需的藍圖。 我們也建議 Azure AI Studio 或 Azure OpenAI Studio 建立與 LLM 整合的 RAG 型 Azure AI 搜尋解決方案。

在 Azure AI 搜尋服務中,所有可搜尋的內容都會儲存在裝載於搜尋服務的搜尋索引中。 搜尋索引是針對具有毫秒響應時間的快速查詢所設計,因此其內部資料結構的存在就是為了支援該目標。 為此,搜尋索引會儲存索引編製內容,而不是整個內容檔案,例如整個 PDF 或影像。 在內部,資料結構包括權杖化文字的反轉索引、內嵌的向量索引,以及需要逐字比對的未修改文字的情況 (例如,在篩選、模糊搜尋、規則運算式查詢中)。

當您設定 RAG 解決方案的資料時,您會使用在 Azure AI 搜尋服務中建立和載入索引的功能。 索引包含重複或代表來源內容的欄位。 索引欄位可能是簡單的轉移 (來源文件中的標題或描述會變成搜尋索引中的標題或描述),或者欄位可能包含外部流程的輸出,例如產生影像表示法或文字描述的向量化或技能處理。

由於您可能知道想要搜尋的內容類型,請考慮適用於每個內容類型的索引編製功能:

內容類型 索引編製為 功能
text 權杖、未更改的文字 索引器可以從 Azure 儲存體和 Cosmos DB 等其他 Azure 資源提取純文字。 您也可以將任何 JSON 內容推送至索引。 若要修改正式發行前小眾測試版中的文字,請使用分析器正規化程式,以在編製索引期間新增語彙處理。 如果來源文件缺少可能在查詢中使用的術語,同義字對應會很有用。
text 向量 1 文字可以在外部進行區塊化和向量化,然後在索引中為向量欄位編製索引
image 權杖、未更改的文字 2 OCR 和影像分析的技能可以處理文字辨識或影像特性的影像。 影像資訊會轉換成可搜尋的文字,並新增至索引。 技能具有索引子需求。
image 向量 1 影像可以從外部向量呈現影像內容,然後編製為索引中的向量欄位。 您可以使用開放原始碼模型,例如 OpenAI CLIP,在相同的內嵌空間中將文字和影像向量化。

1 向量支援的一般可用功能需要您呼叫其他程式庫或模型來進行資料區塊化和向量化。 不過,整合向量化 (預覽) 內嵌這些步驟。 如需這兩種方法的程式碼範例,請參閱 azure-search-vectors 存放庫

2 技能AI 擴充的內建支援。 針對 OCR 和影像分析,編製索引管線會對 Azure AI 視覺 API 進行內部呼叫。 這些技能會將擷取的影像傳遞至 Azure AI 進行處理,並以 Azure AI 搜尋服務所編製索引的文字的形式接收輸出。

向量提供不同內容 (多種檔格式和語言) 的最佳安置方式,因為內容普遍以數學表示形式表達。 向量也支援相似度搜尋:配對最類似於向量查詢的座標。 相較於在標記化字詞上相符的關鍵字搜尋 (或字詞搜尋),相似度搜尋比較細微。 如果內容或查詢中有模棱兩可或解譯需求,則這是較佳的選擇。

一旦您的資料位於搜尋索引中,您就可以使用 Azure AI 搜尋服務的查詢功能來擷取內容。

在非 RAG 模式中,查詢會從搜尋客戶端來回進行。 查詢會被提交,在搜尋引擎上執行,然後將回應傳回給用戶端的應用程式。 回應或搜尋結果只包含索引中找到的逐字內容。

在 RAG 模式中,搜尋引擎與 LLM 之間會協調查詢和回應。 使用者的問題或查詢會以提示轉送至搜尋引擎和 LLM。 搜尋結果會從搜尋引擎傳回,並重新導向至 LLM。 傳回使用者的回應是生成式 AI,可以是 LLM 的加總或答案。

Azure AI 搜尋服務中沒有構成新答案的查詢類型,甚至沒有語意或向量搜尋。 只有 LLM 提供生成式 AI。 以下是 Azure AI 搜尋服務中用來制訂查詢的功能:

查詢功能 目的 使用原因
簡單或完整的 Lucene 語法 對文字和非向量數值內容的查詢執行 全文搜尋最適合完全符合,而不是相似符合。 全文搜索查詢會使用 BM25 演算法設定優先權,並支援透過評分設定檔進行相關性微調。 它也支援篩選和 Facet。
篩選Facet 僅適用於文字或數值 (非向量) 欄位。 依據包含或排除準則減少搜尋介面區。 將精確度新增至您的查詢。
語意排名 使用語意模型重新排名 BM25 結果集。 產生簡短格式的標題和答案,這些標題和答案在 LLM 輸入中很有用。 比評分設定檔更容易,而且視您的內容而定,更可靠的相關性微調技術。
向量搜尋 在向量欄位上執行查詢以進行相似性搜尋,其中查詢字串是一個或多個向量。 向量可以使用任何語言來代表所有類型的內容。
混合式搜尋 結合上述任何或所有查詢技術。 向量和非向量查詢會以平行方式執行,並在統一的結果集中傳回。 精確度和召回率的最顯著提升是透過混合式查詢。

建構查詢回應

查詢的回應會提供 LLM 的輸入,因此搜尋結果的品質對於成功至關重要。 結果為表格式資料列集。 結果的組成或結構取決於:

  • 決定回應中包含索引部分的欄位。
  • 代表索引相符的資料列。

當屬性為「可擷取」時,欄位會出現在搜尋結果中。 索引結構描述中的欄位定義具有屬性,而那些定義會決定是否在回應中使用欄位。 全文或向量查詢結果中只會傳回「可檢索」欄位。 依據預設,會傳回所有「可擷取」欄位,但您可以使用「選取」來指定子集。 除了「可擷取」之外,欄位沒有限制。 欄位可以是任何長度或類型。 關於長度,Azure AI 搜尋服務中沒有欄位長度上限,但有 API 要求的大小限制。

資料列會與查詢相符,並依相關性、相似度或兩者進行排名。 依據預設,結果會限制在全文搜索的前 50 個相符項目,或向量搜尋的 k-near-neighbor 相符項目。 您可以變更預設值,以增加或減少最多 1,000 份文件的限制。 您也可以使用 top 和 skip 分頁參數將結果擷取為一系列分頁結果。

依據相關性排名

當您處理複雜的流程、大量資料並期望毫秒級回應時,每個步驟都必須增加價值並提高最終結果的品質,這一點至關重要。 在資訊擷取端,相關性微調是一項活動,可改善傳送給 LLM 結果的品質。 只有最相關的或最類似的相符文件應該包含在結果中。

相關性適用於關鍵字 (非向量) 搜尋和混合式查詢 (在非向量欄位上)。 在 Azure AI 搜尋服務中,沒有相似度搜尋和向量查詢的相關性微調。 BM25 排名是全文搜尋的排名演算法。

透過增強 BM25 排名的功能支援相關性微調。 這些方法包括:

  • 評分設定檔在特定搜尋欄位中或其他準則中找到相符項目時,會提升搜尋分數。
  • 語意排名重新排名 BM25 結果集,使用 Bing 的語意模型來重新排序結果,以便更適合原始查詢的語意。

在比較和基準測試中,搭配文字和向量欄位的混合式查詢,加上語意排名超過 BM25 排名的結果,會產生最相關的結果。

適用於 RAG 案例的 Azure AI 搜尋服務查詢範例程式碼

下列程式碼會從示範網站的 retrievethenread.py 檔案複製。 它從混合式查詢搜尋結果中為 LLM 產生 content。 您可以撰寫更簡單的查詢,但此範例包含向量搜尋,以及使用語意重新撰寫和拼字檢查的關鍵字搜尋。 在示範中,此查詢是用來取得初始內容。

# Use semantic ranker if requested and if retrieval mode is text or hybrid (vectors + text)
if overrides.get("semantic_ranker") and has_text:
    r = await self.search_client.search(query_text,
                                  filter=filter,
                                  query_type=QueryType.SEMANTIC,
                                  query_language="en-us",
                                  query_speller="lexicon",
                                  semantic_configuration_name="default",
                                  top=top,
                                  query_caption="extractive|highlight-false" if use_semantic_captions else None,
                                  vector=query_vector,
                                  top_k=50 if query_vector else None,
                                  vector_fields="embedding" if query_vector else None)
else:
    r = await self.search_client.search(query_text,
                                  filter=filter,
                                  top=top,
                                  vector=query_vector,
                                  top_k=50 if query_vector else None,
                                  vector_fields="embedding" if query_vector else None)
if use_semantic_captions:
    results = [doc[self.sourcepage_field] + ": " + nonewlines(" . ".join([c.text for c in doc['@search.captions']])) async for doc in r]
else:
    results = [doc[self.sourcepage_field] + ": " + nonewlines(doc[self.content_field]) async for doc in r]
content = "\n".join(results)

整合程式碼和 LLM

包含 Azure AI 搜尋服務的 RAG 解決方案需要其他元件和程式碼才能建立完整的解決方案。 雖然上一節涵蓋透過 Azure AI 搜尋服務擷取的資訊,以及用來建立和查詢可搜尋內容的功能,本節介紹 LLM 整合和互動。

示範存放庫中的筆記本是絕佳的起點,因為它們會顯示將搜尋結果傳遞至 LLM 的模式。 RAG 解決方案中的大部分程式碼都包含對 LLM 的呼叫,因此您必須瞭解這些 API 的運作方式,這超出了本文的範圍。

chat-read-retrieve-read.ipynb 筆記本中的下列資料格區塊會顯示聊天會話內容中的搜尋呼叫:

# Execute this cell multiple times updating user_input to accumulate chat history
user_input = "Does my plan cover annual eye exams?"

# Exclude category, to simulate scenarios where there's a set of docs you can't see
exclude_category = None

if len(history) > 0:
    completion = openai.Completion.create(
        engine=AZURE_OPENAI_GPT_DEPLOYMENT,
        prompt=summary_prompt_template.format(summary="\n".join(history), question=user_input),
        temperature=0.7,
        max_tokens=32,
        stop=["\n"])
    search = completion.choices[0].text
else:
    search = user_input

# Alternatively simply use search_client.search(q, top=3) if not using semantic ranking
print("Searching:", search)
print("-------------------")
filter = "category ne '{}'".format(exclude_category.replace("'", "''")) if exclude_category else None
r = search_client.search(search, 
                         filter=filter,
                         query_type=QueryType.SEMANTIC, 
                         query_language="en-us", 
                         query_speller="lexicon", 
                         semantic_configuration_name="default", 
                         top=3)
results = [doc[KB_FIELDS_SOURCEPAGE] + ": " + doc[KB_FIELDS_CONTENT].replace("\n", "").replace("\r", "") for doc in r]
content = "\n".join(results)

prompt = prompt_prefix.format(sources=content) + prompt_history + user_input + turn_suffix

completion = openai.Completion.create(
    engine=AZURE_OPENAI_CHATGPT_DEPLOYMENT, 
    prompt=prompt, 
    temperature=0.7, 
    max_tokens=1024,
    stop=["<|im_end|>", "<|im_start|>"])

prompt_history += user_input + turn_suffix + completion.choices[0].text + "\n<|im_end|>" + turn_prefix
history.append("user: " + user_input)
history.append("assistant: " + completion.choices[0].text)

print("\n-------------------\n".join(history))
print("\n-------------------\nPrompt:\n" + prompt)

如何開始使用

  • 檢閱索引編製概念和策略以判斷您想要擷取和重新整理資料的方式。 決定是否要使用向量搜尋、關鍵字搜尋或混合式搜尋。 您需要搜尋的內容類型以及要執行的查詢類型決定了索引設計。

  • 檢閱建立查詢以深入瞭解搜尋要求語法和需求。

注意

某些 Azure AI 搜尋服務功能適用於人為互動,且不適用於 RAG 模式。 具體而言,您可以跳過自動完成和建議。 其他功能,例如 Facet 和 orderby 可能很有用,但在 RAG 情節中並不常見。

另請參閱