RAG 的對話記憶挑戰:為何追問失敗是上下文重構問題?

當 RAG 系統面對「那是什麼?」這類追問時,為何總是詞不達意,甚至給出錯誤答案?這不僅是記憶問題,更是「上下文重構」的架構挑戰。本文將深入剖析對話記憶、查詢重寫與檢索狀態的分層治理,揭示為何模糊指代必須在檢索前重構,才能確保 AI 助理的回答精準可靠,避免錯誤接地,建立更值得信賴的對話體驗。

RAG 的對話記憶挑戰:為何追問失敗是上下文重構問題?

當一個基於 RAG(Retrieval-Augmented Generation)的 AI 助理,面對「可以再多解釋一點嗎?」這類追問時,為何經常給出文不對題的答案?這並非單純的記憶遺失,而是更深層的「上下文重構」(Context Reconstruction)失敗所致。許多 RAG 系統將未經處理的模糊指代直接拋給檢索器,導致檢索結果錯誤接地(Grounding),進而影響答案品質。一個穩健的對話式 AI,必須將對話記憶、查詢重寫與檢索狀態進行分層治理,確保傳遞給檢索器的永遠是獨立、完整的查詢指令。這不僅是技術上的優化,更是建立可信任 AI 互動的核心原則。

為什麼 RAG 在追問中容易迷失方向?

標準的 RAG 流程在設計上是無狀態的(Stateless)。它接收一個查詢,從知識庫中檢索相關文件,然後將查詢與文件一起交給大型語言模型(LLM)生成答案。這個模式在處理獨立、完整的單輪問題時非常高效。然而,一旦進入多輪對話,問題就浮現了。

想像一個場景:

  1. 使用者:「Vertex AI 的 RAG Engine 是什麼?」
  2. AI 助理:(執行 RAG 流程)「Vertex AI RAG Engine 是一個...(提供詳細解釋)。」
  3. 使用者:「那它跟 LangChain 的 Retriever 有什麼不同?」

如果系統只是將第三步的「那它跟 LangChain 的 Retriever 有什麼不同?」直接當作新的查詢,檢索器會完全無法理解。它不知道「那它」指的是什麼,因為這個指代詞(pronoun)的上下文存在於對話歷史中,而檢索器本身並未存取這些歷史。結果,檢索器可能回傳不相關的文件,或根本找不到任何結果,最終導致 LLM 生成一個無效或錯誤的答案。這就是典型的「錯誤接地」——模型的回答失去了與現實知識的準確連結。

最近一篇日本開發者部落格的文章,就記錄了一個 Google Chat Bot 在整合 RAG 後遇到的完全相同的困境。開發者發現,機器人無法處理「もう少し詳しく教えて」(再告訴我多一點細節)這類追問,因為系統每次只處理最新的訊息,完全忽略了對話串中的歷史紀錄。

為何說追問失敗,其實是上下文重構的挑戰?

與其將追問失敗歸咎於單純的「記憶」問題,我們更應將其精確定義為「上下文重構」(Context Reconstruction)的架構挑戰。一個成熟的對話式 RAG 系統,絕不應將原始的、帶有模糊指代的對話直接傳遞給檢索器。相反地,它需要一個明確的中介層,負責在檢索前「重構」出一個獨立、完整的查詢。這個複雜的過程,可以巧妙地拆解為以下三個關鍵的治理層次:

  • 首先是對話記憶層(Conversation Memory),這是整個系統的基石。它要求我們建立一個可靠的機制,能持久化儲存完整的對話歷史。例如,前述的日本開發者案例中,便選擇了 Google Firestore 作為對話紀錄的資料庫。無論採用資料庫、記憶體快取或更進階的向量化記憶,其核心目標都是確保系統在任何需要時,都能即時存取先前的互動內容。
  • 其次是查詢重寫層(Query Rewriting),這無疑是整個流程中最關鍵的中介步驟。在將使用者的原始輸入傳遞給檢索器之前,系統應先調用一個 LLM,讓它根據完整的對話歷史和最新的問題,生成一個全新的、上下文完整且獨立的查詢。舉例來說,將模糊的「那它跟 LangChain 的 Retriever 有什麼不同?」重寫為清晰的「Vertex AI RAG Engine 和 LangChain Retriever 之間有什麼不同?」。學術界對此議題已有深入探討,例如 《Query Rewriting for Retrieval-Augmented Large Language Models》這篇論文便詳細分析了多種重寫策略。
  • 最後是檢索狀態層(Retrieval State),這代表著最終傳遞給檢索器的資訊。此層的查詢必須是經過重寫後、清晰明確的指令,完全剝離了對話的動態與模糊性。檢索器不應被賦予理解對話上下文的責任,其任務應保持單純。
檢索器的任務是根據明確的指令找出最相關的文件,而不是猜測對話中的模糊指代。將上下文理解的責任交還給語言模型,才是正確的架構分工。

如何實作一個穩健的上下文重構流程?

基於上述的分層概念,我們可以設計一個更穩健的對話式 RAG 流程。以前述的 Google Chat Bot 為例,一個可行的實作路徑如下:

首先,在技術選型上,該專案採用了 Google Cloud Functions (2nd gen) 搭配 Python 3.14,並使用 Gemini 2.5 Flash 作為 LLM,後端則串接 Vertex AI RAG Engine。當收到使用者訊息時,系統的處理流程不再是直接檢索,而是:

  1. 儲存與讀取歷史:當系統接收到使用者訊息時,首先會將其存入 Firestore,並同時讀取該對話串的最近幾輪歷史紀錄,為後續的上下文重構做準備。
  2. 執行查詢重寫:接著,系統會將完整的對話歷史與最新的問題打包成一個精心設計的 prompt,發送給 Gemini 2.5 Flash。這個 prompt 的核心指令是:「請根據以下的對話歷史,將最後一個問題改寫成一個獨立、完整的查詢。如果問題本身已經很完整,則無需改寫。」確保生成一個無歧義的查詢。
  3. 執行檢索:隨後,將 LLM 重寫後的清晰查詢,傳遞給 Vertex AI RAG Engine。此刻,RAG Engine 收到的是一個明確、不需額外上下文就能理解的指令,專注於高效檢索相關文件。
  4. 生成最終答案:最後,系統會將重寫後的查詢與檢索到的文件,一同交給 LLM 進行最終的答案生成。這個答案會回傳給使用者,同時也會存入 Firestore,成為新的對話歷史,為未來的互動累積上下文。

這個架構的核心,是透過查詢重寫明確地分離了「理解對話」和「檢索知識」這兩個任務。諸如 LangChain 的 `create_history_aware_retriever` 等框架也內建了類似的機制,證明這已是業界建立可靠對話式 AI 的標準實踐。將上下文重構視為一個獨立的、必須主動治理的環節,而非被動依賴 LLM 的「聰明才智」,才能打造出在長期互動中依然表現穩定、可預測的 AI 系統。

我是江中喬,專注於 AI Agent Architecture、Memory Governance 與 Cognitive Diversity,持續研究如何打造能夠長期協作、可信任且可治理的 AI 系統。

延伸閱讀