在 Azure AI 搜尋中擷取擴增產生 (RAG)

擷取擴增世代 (RAG) 是一種架構,可藉由新增提供地面數據的資訊擷取系統,來增強 ChatGPT 等大型語言模型 (LLM) 的功能。 新增資訊擷取系統可讓您控制 LLM 在制定回應時所使用的地面數據。 針對企業解決方案,RAG 架構表示,如果您已內嵌該內容的模型,您可以將產生 AI 限制為 來自向量化檔和影像的企業內容 ,以及其他數據格式。

決定要使用的資訊擷取系統很重要,因為它會決定 LLM 的輸入。 資訊擷取系統應該提供:

  • 針對您所有內容大規模載入和重新整理的索引編製策略,其頻率是您需要的。

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

  • 數據和作業的安全性、全球觸達和可靠性。

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

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

注意

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

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

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

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

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

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

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

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

使用 search 和 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 token、unaltered text 索引器可以從其他 Azure 資源提取純文字,例如 Azure 儲存體 和 Cosmos DB。 您也可以 將任何 JSON 內容 推送至索引。 若要修改正式發行前小眾測試版中的文字,請使用分析器和正規化程式在編製索引期間新增語匯處理。 如果源檔遺漏查詢中可能使用的術語,同義字對應 會很有用。
text vectors 1 文字可以在外部進行區塊化和向量化,然後 以索引中的向量字段 編製索引。
image token, unaltered text 2 OCR 和影像分析的技能 可以處理文字辨識或影像特性的影像。 影像資訊會轉換成可搜尋的文字,並新增至索引。 技能具有索引器需求。
image vectors 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 份檔的限制。 您也可以使用頂端和略過分頁參數,以一系列分頁結果的形式擷取結果。

依相關性排名

當您使用複雜的程式、大量數據,以及毫秒響應的預期時,每個步驟都會增加價值並改善最終結果的品質非常重要。 在資訊擷取端,相關性微調是一項活動,可改善傳送至 LLM 的結果品質。 只有最相關的或最類似的比對文件應該包含在結果中。

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

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

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

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

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

# 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 Notebook 中的下列數據格區塊會顯示聊天會話內容中的搜尋呼叫:

# 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 案例中並不常見。

另請參閱