為 AI agent 構建智能上下文記憶

memory(記憶)是任何有效 ai agent 的基礎組件。在最核心的層面,memory 存的是過去的用戶交互和上下文信息,讓 agent 在時間維度上做出更準確的響應。一個 agent 僅靠配置好的大語言模型(large language model,llm)和工具就能跑起來,但真正的可靠性和個性化來自 memory。

memory 讓 agent 在多次交互之間保留對話上下文,這樣即使是多個 agent 協作完成任務也一樣。這種上下文連續性讓系統能更準確地把握用戶意圖,輸出與預期對得上的響應。

當 agent 同時拿到當前輸入和相關上下文時,它產出的內容會更有依據。視情況,agent 可能:

  • 觸發一次工具調用

  • 向用戶請求澄清

  • 直接給出最終響應

memory 把 ai agent 從被動響應的系統,變成具備上下文感知的助手。

為什麼不把全部歷史交互都丟給 llm

 messages: annotated[list[basemessage], add_messages]

context window 一旦做大,最簡單的做法就是每次新請求都把過去所有用戶交互(有時甚至跨多個會話)一起發過去,讓模型完全靠 attention 機制自己解讀。

這種策略實現簡單,對短期、小規模的任務表現良好。但對話一長問題就來了:

  • 模型容易被過多且無關的上下文淹沒 ⚠️

  • attention 機制本身不透明,輸出會出現不一致

  • 同一類輸入產生不同響應,開發者很難定位原因

  • token 用量隨每輪交互增長,成本明顯上去 💰

  • 上下文越大,處理時間越長,延遲也跟着上 ⏱️

對話歷史不斷膨脹,每條查詢的處理成本越來越高,響應越來越慢,對生產級 agent 系統尤其不友好。

由此引出一個關鍵問題:怎麼把上下文壓下去,又不丟相關性?

rolling context window

一種替代做法是限定一個最近交互的最大數量發送給模型,這種技術被稱為 rolling context window。

只保留最近的 n 次交互,開發者就能:

  • 控制 token 用量

  • 降低延遲

  • 把成本維持在可預測區間

這種做法適用於任務主要依賴近期對話歷史的場景。但對那些需要較舊或長期信息的 agent,硬切窗口會讓理解殘缺、輸出不準。

註:rolling window 既可以按消息數計,也可以按 token 計。

 window_size = 6  #added a wrapper method for return window messages  def rolling_add_messages(oldnew):    combined = add_messages(oldnew)    return combined[-window_size:]  class agentstate(typeddict):     messages: annotated[list[basemessage], rolling_add_messages]

用倒排索引做更聰明的上下文裁剪

倒排索引是一種數據庫數據結構,把內容(詞或數字)直接映射到它在文檔或文檔集合中出現的位置,用於實現極快的全文檢索。

在聊天歷史上構建一個倒排索引,用戶提交查詢時檢索與查詢中的詞最匹配的上下文。

把所有相關匹配交給模型。這樣發給基礎模型的上下文量會顯著縮小,同時仍然保留最相關的信息 ,哪怕這些信息來自對話很早的部分。

但僅靠精確詞匹配未必夠用,查詢可能用了語義相近、但用詞不同的表達,結果就是上下文檢索不完整,可能引出錯誤輸出或幻覺,語義上接近的查詢甚至會拿到完全不同的回應。

一個最簡單的倒排索引構建與搜索可以這樣寫:

 def build_inverted_index(messages):      index = defaultdict(set)      for i, msg in enumerate(messages):          words = msg.lower().split()          for word in words:              index[word].add(i)      return index  def search_context(query, index, messages):      query_words = query.lower().split()      matched_ids = set()      for word in query_words:          if word in index:              matched_ids.update(index[word])       return [messages[i] for i in matched_ids]

語義上下文檢索

語義檢索是一種數據檢索技術,它解讀用戶意圖和查詢的上下文含義,而不僅僅匹配關鍵詞。

不依賴精確詞匹配可以用語義上下文檢索。語義檢索保留用戶意圖,按含義而非具體詞去取回上下文消息,能壓住幻覺,讓 agent 響應更准、更可靠。

句子先被切成 token,然後用輕量級 ai embedding 模型把每個 token 轉成向量。每個 token 向量會基於周圍詞提供的上下文做細化。這些 token 向量再被聚合成一個表示整句含義的句子向量,存入向量數據庫。

用戶提交查詢時,查詢同樣會被轉成向量,並使用 cosine similarity 與庫中存儲的向量比較:

similarity = cos(angle between vectors)

接近 0.9 的相似度分數說明含義高度相近,低於 0.3 通常說明兩句無關。具體閾值視應用而定。檢索出的最相關上下文隨後被送入基礎模型生成響應。

下面這段示例代碼使用 sentence transformers 生態中的輕量預訓練 sentence-embedding 模型,配合 faiss作為內存向量數據庫做語義檢索。

 from sentence_transformers import sentencetransformer  import faiss  import numpy as np  # sample data  sentences = [      "schedule meeting tomorrow",      "send project report",      "prepare meeting agenda"  ]  # load embedding model  model = sentencetransformer("all-minilm-l6-v2")  # convert sentences into vectors  embeddings = model.encode(sentences)  # create faiss index  index = faiss.indexflatl2(embeddings.shape[1])  index.add(np.array(embeddings))  # search  query = "plan meeting"  query_vector = model.encode([query])  distances, indices = index.search(np.array(query_vector), k=2)   print([sentences[i] for i in indices[0]])

語義經驗記憶

每條用戶查詢通常從一個乾淨狀態開始,沒有以前交互里積累的知識,所以體驗上就會顯得不完整、不夠個性化。

更好的做法是:用戶每次提交查詢,系統就跨過去的交互檢索語義相似、可能對當前請求有幫助的上下文。context window 要做切分 —— 一部分留給最近對話,一部分留給語義檢索取回的相關歷史。

這樣 agent 就能基於用戶偏好和先前交互調整響應,體驗更一致、更個性化、更熟悉。

這就是把先前獲得的知識當作經驗,用來增強當前用戶查詢的地方。

graph rag

跨上下文檢索本身就不容易,尤其是相關知識分散在多次交互或多份文檔里時。純語義檢索往往只覆蓋所需信息的一部分,那些語義不同但邏輯上相關的重要細節會被漏掉。

舉個例子:用戶問 "why was the payment delayed?",語義檢索可能取回帶有 payment delay 或 transaction pending 的消息,但很容易漏掉 "approval from finance team is pending" 或 "compliance verification not completed" 這類陳述 —— 它們和延遲在邏輯上是連在一起的,但用詞差太多,相似度方法抓不到。

這就是 graphrag起作用的地方,它把信息表示成一張圖:文檔或概念是節點,關係是邊,從而支持更有結構、更有連通性的上下文檢索。

但麻煩是:當知識圖譜必須隨着運行時不斷引入的新信息動態更新時,維護和演進這張圖,在計算和設計兩端都會帶來不小的開銷。

構建知識圖譜通常包含這些步驟:

  1. 識別節點(實體或概念)

  2. 識別節點之間的關係

  3. 定義本體(圖的結構與 schema)

  4. 用數據填充圖

這種結構化表示能比單純語義相似度取回更豐富、更有連接性的上下文,讓響應更完整,也減少相關知識之間被漏掉的連接。

可以使用 microsoft 的 graphrag 庫,自動從內容中識別實體(節點)和關係,並據此構建知識圖譜。

step 1:初始化項目目錄

安裝 graphrag 並創建工作目錄:

 pip install graphrag   graphrag init --root ./graphrag_demo

命令會創建如下結構:

graphrag_demo/├── input/├── settings.yaml└── prompts/把源文檔放進 input/ 文件夾。

step 2:構建知識圖譜

運行 indexing 命令,提取實體、檢測關係、構建圖:

 graphrag index --root ./graphrag_demo

step 3:查詢圖譜

直接對生成好的知識圖譜發起查詢:

 graphrag query \    — root ./graphrag_demo \    — method global \    "why was the payment delayed?"

系統會跨圖檢索互相連接的上下文,從而支持多跳推理,而不僅僅是語義相似度。

總結

現代 ai agent 想給出準確且個性化的響應,光靠關鍵詞匹配或孤立的語義相似度是不夠的。倒排索引能高效縮小上下文規模,語義檢索能保住意圖,但兩條路都可能漏掉散落在多份知識里的關係。

graphrag 把信息組織成相互關聯的實體和關係,讓跨上下文的多跳推理成為可能,而不只是取回相似的文本片段。agent 也因此從表層檢索走向對概念之間關係的更深理解。

把 rolling context window、語義相似度檢索、經驗記憶和基於圖的檢索結合起來,就能構建出不只會回憶、還會推理的 agent。這樣的系統給出的答案更完整,幻覺更少,體驗也更個性化、更一致。

agent memory 的未來在於從存儲信息轉向連接知識,讓 ai 系統從上下文感知的助手,進一步演進為具備上下文推理能力的協作者。

by mudassir fazal

點個 在看 你最好看!