Mem0:新一代 AI Agent 的持久化記憶體系

一、Mem0 簡介

Mem0 是一個輕量級、可擴展的長期記憶框架,支持本地部署和雲端使用。其設計初衷是爲 LLM 提供結構化的記憶支持,幫助智能體記住用戶偏好、背景信息等,從而提供更個性化、更連貫的回答。

1. 基本特性

記憶處理:利用大型語言模型自動從對話中提取並存儲關鍵信息,同時保持完整的上下文語境

記憶管理:持續更新存儲信息並消除矛盾點,確保數據準確性

雙重存儲架構:結合向量數據庫(用於記憶存儲)和圖數據庫(用於關係追蹤)的混合存儲方案

智能檢索系統:採用語義搜索與圖查詢技術,根據信息重要性和時效性檢索相關記憶

便捷 API 集成:提供簡單易用的記憶添加(add)與檢索(search)接口端點

2. 安裝方式

安裝只需一行命令:

pip install mem0ai

二、初始化與基本操作

1. 初始化

from mem0 import Memory
import os

os.environ["OPENAI_API_KEY"] = "your-api-key"  # 用於 embedding
m = Memory()

或者使用異步版本:

from mem0 import AsyncMemory
m = AsyncMemory()

2. 添加記憶

添加記憶將利用大型語言模型自動從對話中提取並存儲關鍵信息:

messages = [
    {"role": "user", "content": "我今晚想看電影,有什麼推薦?"},
]

m.add(messages, user_id="alice", metadata={"category": "電影推薦"})

也可關閉自動推理,不做關鍵信息的提取,直接保存原始對話:

m.add(messages, user_id="alice", infer=False)

3. 檢索記憶

● 獲取所有記憶:

all_memories = m.get_all(user_id="alice")

● 查詢特定記憶:

memory = m.get("memory_id")

● 搜索相關記憶:

related = m.search("我喜歡什麼電影?", user_id="alice")

4. 更新、刪除與重置記憶

● 更新:

m.update(memory_id="xxx", data="我愛看動作電影")

● 刪除單條或全部記憶:

m.delete("memory_id")
m.delete_all(user_id="alice")

● 重置所有記憶:

m.reset()

5. 兼容 OpenAI 客戶端的完整示例

Mem0 提供兼容 OpenAI 的 chat.completions.create()接口,方便無縫集成,每次調用都會自動添加記憶以及查找記憶

from mem0.proxy.main importMem0

client =Mem0(api_key="your-api-key")
messages =[{"role":"user","content":"我喜歡印度菜,但不能喫奶酪。"}]
user_id ="alice"

# 第一次交互
client.chat.completions.create(messages=messages, model="gpt-4o-mini", user_id=user_id)

# 第二次交互將自動利用記憶生成更合理的答案
messages =[{"role":"user","content":"推薦舊金山好喫的餐廳"}]
reply = client.chat.completions.create(messages=messages, model="gpt-4o-mini", user_id=user_id)
print(reply.choices[0].message.content)

輸出示例中將結合用戶 “不能喫奶酪” 的偏好,避免推薦含奶的餐廳。

三、核心概念

1. 兩種主要的記憶類型

1.1 短期記憶

AI 系統中最基礎的記憶形式,用於存儲即時上下文信息——類似於人類記住對話中剛剛提及的內容。主要包括:

● 對話歷史:最近的交互消息及其順序

● 工作記憶:臨時變量和狀態信息

● 注意力上下文:當前對話的焦點內容

1.2 長期記憶

更先進的 AI 應用會部署長期記憶系統,實現跨對話的信息留存。具體包含:

● 事實性記憶:關於用戶特徵、偏好及領域知識的存儲

● 情景記憶:過往交互記錄與經歷

● 語義記憶:對概念及其關聯關係的理解

Mem0 通過以下方式構建長期記憶系統:

● 採用向量嵌入技術存儲和檢索語義信息

● 跨會話維持用戶專屬上下文

● 建立高效檢索機制,精準調用相關歷史交互

2. Mem0 的兩個主要接口

● add:用於存儲對話內容並轉化爲記憶

● search:基於查詢條件獲取相關記憶

2.1 記憶寫入流程

寫入操作通過多階段處理對話內容:

a. 信息提取

● 大語言模型從對話中提取關鍵記憶

● 識別重要實體及其關聯關係

b. 衝突處理

● 系統比對新舊數據

● 自動檢測並解決信息矛盾

c. 記憶存儲

● 向量數據庫存儲記憶本體

● 圖數據庫維護關係網絡

● 每次交互後實時更新記憶庫

2.2 記憶檢索流程

檢索操作通過智能分層處理實現精準召回:

a. 查詢優化

● 大語言模型解析並優化搜索語句

● 系統預置定向篩選條件

b. 向量搜索

● 執行基於語義的向量相似度匹配

● 按關聯度對結果排序

● 支持多維篩選(用戶 / 代理 / 元數據等)

c. 結果合成

● 聚合並優化搜索結果

● 返回帶相關性評分的記憶內容

● 包含完整元數據及時間戳

四、其他特性

1. 完全兼容 OpenAI 規範

可以像操作 OpenAI 客戶端一樣的方式來操作 Mem0 客戶端,接口完全通用:

from mem0.proxy.main importMem0

client =Mem0(api_key="m0-xxx")

# First interaction: Storing user preferences
messages =[
{
"role":"user",
"content":"I love indian food but I cannot eat pizza since allergic to cheese."
},
]
user_id ="alice"
chat_completion = client.chat.completions.create(
    messages=messages,
    model="gpt-4o-mini",
    user_id=user_id
)
# Memory saved after this will look like: "Loves Indian food. Allergic to cheese and cannot eat pizza."

# Second interaction: Leveraging stored memory
messages =[
{
"role":"user",
"content":"Suggest restaurants in San Francisco to eat.",
}
]

chat_completion = client.chat.completions.create(
    messages=messages,
    model="gpt-4o-mini",
    user_id=user_id
)
print(chat_completion.choices[0].message.content)
# Answer: You might enjoy Indian restaurants in San Francisco, such as Amber India, Dosa, or Curry Up Now, which offer delicious options without cheese.

如需自定義相關配置(如向量數據庫信息),則可以在初始化 Mem0 客戶端的時候加入config參數:

config = {
"vector_store":{
"provider":"qdrant",
"config":{
"host":"localhost",
"port":6333,
}
},
}

client =Mem0(config=config)

chat_completion = client.chat.completions.create(
    messages=[
{
"role":"user",
"content":"What's the capital of France?",
}
],
    model="gpt-4o",
)

2. 提示詞配置

用戶可以根據實際應用自行修改或者配置以下兩種提示詞。

2.1 關鍵信息提取 Prompt

關鍵信息提取允許根據特定使用場景或專業領域,定製 Mem0 的信息處理行爲。通過定義該提示,可以精確控制如何從用戶消息中提取關鍵信息。

建議遵循以下原則

● 明確指定需要提取的信息類型

● 提供少量示例(few-shot)引導語言模型

● 確保示例遵循標準格式規範

以下是官方給出的示例:

custom_fact_extraction_prompt = """
Please only extract entities containing customer support information, order details, and user information. 
Here are some few shot examples:

Input: Hi.
Output: {{"facts" : []}}

Input: The weather is nice today.
Output: {{"facts" : []}}

Input: My order #12345 hasn't arrived yet.
Output: {{"facts" : ["Order #12345 not received"]}}

Input: I'm John Doe, and I'd like to return the shoes I bought last week.
Output: {{"facts" : ["Customer name: John Doe", "Wants to return shoes", "Purchase made last week"]}}

Input: I ordered a red shirt, size medium, but received a blue one instead.
Output: {{"facts" : ["Ordered red shirt, size medium", "Received blue shirt instead"]}}

Return the facts and customer information in a json format as shown above.
"""

2.2 記憶更新 Prompt

記憶更新是用於決定對記憶執行何種操作的控制指令。通過自定義該提示,可以精確控制記憶的更新機制。

Mem0 會將新提取的事實與現有記憶進行比對,並自動決定採取以下操作之一:

● 新增(Add):將新事實添加至記憶庫

● 更新(Update):用新事實修正現有記憶內容

● 刪除(Delete):移除現有記憶條目

● 保持(No Change):不執行任何記憶變更

以下是官方給出的示例:

UPDATE_MEMORY_PROMPT = """You are a smart memory manager which controls the memory of a system.
You can perform four operations: (1) add into the memory, (2) update the memory, (3) delete from the memory, and (4) no change.

Based on the above four operations, the memory will change.

Compare newly retrieved facts with the existing memory. For each new fact, decide whether to:
- ADD: Add it to the memory as a new element
- UPDATE: Update an existing memory element
- DELETE: Delete an existing memory element
- NONE: Make no change (if the fact is already present or irrelevant)

There are specific guidelines to select which operation to perform:

1. **Add**: If the retrieved facts contain new information not present in the memory, then you have to add it by generating a new ID in the id field.
- **Example**:
    - Old Memory:
        [
            {
                "id" : "0",
                "text" : "User is a software engineer"
            }
        ]
    - Retrieved facts: ["Name is John"]
    - New Memory:
        {
            "memory" : [
                {
                    "id" : "0",
                    "text" : "User is a software engineer",
                    "event" : "NONE"
                },
                {
                    "id" : "1",
                    "text" : "Name is John",
                    "event" : "ADD"
                }
            ]

        }

2. **Update**: If the retrieved facts contain information that is already present in the memory but the information is totally different, then you have to update it. 
If the retrieved fact contains information that conveys the same thing as the elements present in the memory, then you have to keep the fact which has the most information. 
Example (a) -- if the memory contains "User likes to play cricket" and the retrieved fact is "Loves to play cricket with friends", then update the memory with the retrieved facts.
Example (b) -- if the memory contains "Likes cheese pizza" and the retrieved fact is "Loves cheese pizza", then you do not need to update it because they convey the same information.
If the direction is to update the memory, then you have to update it.
Please keep in mind while updating you have to keep the same ID.
Please note to return the IDs in the output from the input IDs only and do not generate any new ID.
- **Example**:
    - Old Memory:
        [
            {
                "id" : "0",
                "text" : "I really like cheese pizza"
            },
            {
                "id" : "1",
                "text" : "User is a software engineer"
            },
            {
                "id" : "2",
                "text" : "User likes to play cricket"
            }
        ]
    - Retrieved facts: ["Loves chicken pizza", "Loves to play cricket with friends"]
    - New Memory:
        {
        "memory" : [
                {
                    "id" : "0",
                    "text" : "Loves cheese and chicken pizza",
                    "event" : "UPDATE",
                    "old_memory" : "I really like cheese pizza"
                },
                {
                    "id" : "1",
                    "text" : "User is a software engineer",
                    "event" : "NONE"
                },
                {
                    "id" : "2",
                    "text" : "Loves to play cricket with friends",
                    "event" : "UPDATE",
                    "old_memory" : "User likes to play cricket"
                }
            ]
        }


3. **Delete**: If the retrieved facts contain information that contradicts the information present in the memory, then you have to delete it. Or if the direction is to delete the memory, then you have to delete it.
Please note to return the IDs in the output from the input IDs only and do not generate any new ID.
- **Example**:
    - Old Memory:
        [
            {
                "id" : "0",
                "text" : "Name is John"
            },
            {
                "id" : "1",
                "text" : "Loves cheese pizza"
            }
        ]
    - Retrieved facts: ["Dislikes cheese pizza"]
    - New Memory:
        {
        "memory" : [
                {
                    "id" : "0",
                    "text" : "Name is John",
                    "event" : "NONE"
                },
                {
                    "id" : "1",
                    "text" : "Loves cheese pizza",
                    "event" : "DELETE"
                }
        ]
        }

4. **No Change**: If the retrieved facts contain information that is already present in the memory, then you do not need to make any changes.
- **Example**:
    - Old Memory:
        [
            {
                "id" : "0",
                "text" : "Name is John"
            },
            {
                "id" : "1",
                "text" : "Loves cheese pizza"
            }
        ]
    - Retrieved facts: ["Name is John"]
    - New Memory:
        {
        "memory" : [
                {
                    "id" : "0",
                    "text" : "Name is John",
                    "event" : "NONE"
                },
                {
                    "id" : "1",
                    "text" : "Loves cheese pizza",
                    "event" : "NONE"
                }
            ]
        }
"""

五、總結

Mem0 作爲一個易用、靈活且功能強大的記憶增強框架,極大地擴展了大語言模型的上下文記憶能力。無論是構建常見的多輪對話機器人、智能搜索系統還是個性化推薦服務,Mem0 都是一個非常值得嘗試的工具。

你好,我是 William,一名喜歡折騰的程序員。曾擔任大廠算法工程師,現在初創公司做 AI 應用全棧開發。

本文由 Readfog 進行 AMP 轉碼,版權歸原作者所有。
來源https://mp.weixin.qq.com/s/1TUoquan8aCFx-aK6_J1-Q