MemPalace 與 Milvus
MemPalace是一個專為程式設計代理和長期運行的開發工作流程所設計的記憶層。它將專案知識組織成「翼」、「房間」和「抽屜」,並使原始內容能在不同工作階段間進行搜尋。
在本教學中,我們將使用 MemPalace CLI 從公開的 Milvus 文件中擷取一個真實的子集,並將其儲存至Milvus。該語料庫包含關於分析器、分詞器及詞元篩選器的文件。這些密切相關的頁面提供了足夠的干擾項,使檢索範例更具實用價值。
本範例使用 Milvus Lite,因此無需 Docker 或獨立的資料庫伺服器即可在本地執行。相同的 MemPalace 配置亦可指向 Milvus 伺服器或 Zilliz Cloud,以進行共享部署。
先決條件
請從 PyPI 安裝 MemPalace 及其可選的 Milvus 依賴項。此指令刻意未鎖定特定版本,因此新安裝時會自動採用最新可用版本。
uv tool install "mempalace[milvus]"
您還需要 Git 來下載文件語料庫。
本教學使用 MemPalace 的本地 MiniLM 嵌入式模型,因此無需外部模型 API 金鑰。首次執行挖掘或搜尋指令時,可能會下載一個小型 ONNX 嵌入式模型。
設定工作區
建立一個工作區,並為文件資料集和 MemPalace 分別設定獨立目錄:
mkdir -p mempalace-milvus-demo
cd mempalace-milvus-demo
export PALACE_DIR="$PWD/palace"
export DOCS_REPO="$PWD/milvus-docs"
export PROJECT_DIR="$PWD/milvus-analyzer-docs"
export MEMPALACE_EMBEDDING_MODEL="minilm"
export MEMPALACE_EMBEDDING_DEVICE="cpu"
export MEMPALACE_EMBEDDING_THREADS="2"
我們將 `--backend milvus ` 傳遞給下方的 MemPalace 指令。由於未配置遠端 Milvus URI,MemPalace 會在 `$PALACE_DIR/milvus.db` 建立一個本機 Milvus Lite 資料庫。
至於後端所使用的
MilvusClient參數:
- 將
uri設定為本機路徑(例如./milvus.db)是最便捷的選項。此設定會自動使用Milvus Lite將資料儲存於本機。- 若需進行較大規模的部署,您可以使用Milvus 伺服器,並將 URI 設定為其端點,例如
http://localhost:19530。- 若要使用Zilliz Cloud,請將 URI 和 token 設定為該叢集的公開端點和 API 金鑰。
下載 Milvus 文件資料庫
Milvus 文件儲存庫的規模遠大於此範例所需。請使用 Git 稀疏檢出功能,僅從v3.0.x 分支下載 Analyzer 文件目錄:
git clone \
--depth 1 \
--filter=blob:none \
--sparse \
--branch v3.0.x \
https://github.com/milvus-io/milvus-docs.git \
"$DOCS_REPO"
git -C "$DOCS_REPO" sparse-checkout set \
site/en/userGuide/schema/analyzer
cp -R \
"$DOCS_REPO/site/en/userGuide/schema/analyzer" \
"$PROJECT_DIR"
撰寫本文時,此目錄包含 31 個 Markdown 頁面。其中包含 Analyzer 的通用指南,以及三組密切相關的頁面:
milvus-analyzer-docs/
├── analyzer/ # Built-in language analyzers
├── filter/ # Token filters
├── tokenizer/ # Tokenizers
└── *.md # Analyzer overviews and selection guides
確認原始頁面數量:
find "$PROJECT_DIR" -type f -name "*.md" | wc -l
參考輸出:
31
隨著 Milvus 文件分支的更新,確切的頁數可能會有所變動。
定義 MemPalace 房間
MemPalace 能在「mempalace init 」過程中偵測房間,但其初始化流程也會執行全專案範圍的啟發式實體分類,並將通過驗證的結果寫入實體註冊表。由於定義此文件語料庫時無需進行該分類步驟,因此我們直接提供簡要的分類體系。 在資料挖掘過程中,MemPalace 仍可能會附加確定性的啟發式實體元資料,並建立內部走廊連結;這些關聯並不會決定檔案應歸入哪個房間,也不會影響下文所述的房間範圍內搜尋。
建立名為 `$PROJECT_DIR/mempalace.yaml ` 的檔案,內容如下:
wing: milvus_analyzer_docs
rooms:
- name: analyzer
description: Built-in language analyzers and analyzer selection guides
keywords:
- analyzer
- name: filter
description: Token filters used in analyzer pipelines
keywords:
- filter
- name: tokenizer
description: Tokenizers and language identification
keywords:
- tokenizer
- name: general
description: Analyzer documentation that does not fit another room
keywords: []
「翼」(wing)代表整個文件集。一個「房間」(room)則代表一個主題領域。MemPalace 會先檢查檔案的目錄,接著檢查檔案名稱,最後檢查內容中的房間關鍵字,以此來路由檔案。例如,位於filter/ 下的檔案,會直接進入「filter 」房間。
接著,每個檔案會被分割成相互重疊的文字區塊。每個區塊都會成為一個「抽屜」,內含原文字體的 Markdown 內容以及諸如wing 、room 、source_file 、chunk_index 及原始碼行號等元資料。這些「房間」與「抽屜」在 MemPalace 的 Milvus 集合中僅作為邏輯元資料存在;MemPalace 並不會為每個「房間」建立獨立的 Milvus 集合。
將文件導入 Milvus
使用 Milvus 後端對專案進行資料挖掘:
mempalace \
--palace "$PALACE_DIR" \
mine "$PROJECT_DIR" \
--backend milvus
參考已驗證文件快照的輸出結果:
=======================================================
Done.
Files processed: 31
Files skipped (already filed or other): 0
Drawers filed: 473
By room:
filter 16 files
analyzer 8 files
tokenizer 7 files
=======================================================
MemPalace 會直接讀取 Markdown 內容(不會進行摘要或重寫),計算局部嵌入向量,並將抽屜儲存至 Milvus 中。在測試的文件快照中,31 個檔案共產生了 473 個抽屜。
檢查生成的房間與抽屜數量:
mempalace --palace "$PALACE_DIR" status --backend milvus
參考輸出:
=======================================================
MemPalace Status -- 473 drawers
=======================================================
WING: milvus_analyzer_docs
ROOM: analyzer 212 drawers
ROOM: filter 156 drawers
ROOM: tokenizer 105 drawers
=======================================================
當上游文件內容變更時,確切的「抽屜」數量可能會有所變化,因為較長的頁面會產生更多片段。
語義搜尋
使用mempalace search 根據語義檢索文件。以下問題並未指定特定檔案或 Analyzer 功能:
mempalace \
--palace "$PALACE_DIR" \
search "How should I analyze documents that mix several languages?" \
--backend milvus \
--wing milvus_analyzer_docs \
--results 3
參考輸出(分數可能有所不同):
Results for: "How should I analyze documents that mix several languages?"
Wing: milvus_analyzer_docs
[1] milvus_analyzer_docs / analyzer
Source: multi-language-analyzers.md
Match: cosine_sim=0.334 bm25=2.469
[2] milvus_analyzer_docs / analyzer
Source: multi-language-analyzers.md
[3] milvus_analyzer_docs / analyzer
Source: multi-language-analyzers.md
在經過驗證的執行中,儘管語料庫中也包含各語言分析器、分詞器及過濾器的獨立頁面,但這三項結果均來自multi-language-analyzers.md 。
在房間內搜尋
當相關概念散見於整個語料庫時,房間篩選器便十分實用。以下查詢僅在「filter 」房間內搜尋,以找出讓等效術語能相互匹配的方法:
mempalace \
--palace "$PALACE_DIR" \
search "How can equivalent terms such as USA and United States match one another?" \
--backend milvus \
--wing milvus_analyzer_docs \
--room filter \
--results 3
參考輸出(分數可能有所不同):
Results for: "How can equivalent terms such as USA and United States match one another?"
Wing: milvus_analyzer_docs
Room: filter
[1] milvus_analyzer_docs / filter
Source: synonym-filter.md
Match: cosine_sim=0.765 bm25=2.573
[2] milvus_analyzer_docs / filter
Source: stemmer-filter.md
[3] milvus_analyzer_docs / filter
Source: stop-filter.md
首個結果應來自synonym-filter.md 。房間限制是透過抽屜元數據在向量搜尋前套用,因此詞元化器與語言分析器的抽屜均被排除在此搜尋之外。
搜尋精確術語
MemPalace CLI 在對向量搜尋候選結果進行排序時,會將語義相似度與 BM25 訊號結合。因此,使用精確的配置名稱和功能名稱,無需切換至獨立的 CLI 搜尋模式,即可改善排序結果。
mempalace \
--palace "$PALACE_DIR" \
search "language_identifier tokenizer" \
--backend milvus \
--wing milvus_analyzer_docs \
--room tokenizer \
--results 3
參考輸出(分數可能有所不同):
Results for: "language_identifier tokenizer"
Wing: milvus_analyzer_docs
Room: tokenizer
[1] milvus_analyzer_docs / tokenizer
Source: language-identifier.md
Match: cosine_sim=0.420 bm25=0.969
[2] milvus_analyzer_docs / tokenizer
Source: language-identifier.md
[3] milvus_analyzer_docs / tokenizer
Source: lindera-tokenizer.md
搜尋結果應優先顯示language-identifier.md ,該頁面記載了language_identifier 標記器,該標記器會根據偵測到的語言來選擇分析器。
檢視 Milvus 集合
MemPalace 會自動管理其 Milvus 資料結構。若要確認儲存的內容,請將以下腳本儲存為inspect_milvus.py 。該腳本會開啟相同的 Milvus Lite 資料庫,檢視集合,並按房間統計抽屜數量:
import os
from collections import Counter
from pymilvus import MilvusClient
client = MilvusClient(uri=os.environ["MEMPALACE_MILVUS_LITE_PATH"])
for collection_name in sorted(client.list_collections()):
stats = client.get_collection_stats(collection_name)
schema = client.describe_collection(collection_name)
fields = [field["name"] for field in schema["fields"]]
print(f"{collection_name}: rows={stats['row_count']}, fields={fields}")
client.load_collection("mempalace_drawers")
rows = client.query(
collection_name="mempalace_drawers",
filter='metadata["wing"] == "milvus_analyzer_docs"',
limit=2000,
output_fields=["metadata"],
)
room_counts = Counter(row["metadata"]["room"] for row in rows)
print("Drawers by room:", dict(sorted(room_counts.items())))
請使用與 CLI 相同的可選依賴項集來執行此腳本:
export MEMPALACE_MILVUS_LITE_PATH="$PALACE_DIR/milvus.db"
uv run --with "mempalace[milvus]" inspect_milvus.py
參考輸出:
mempalace_closets: rows=74, fields=['id', 'document', 'metadata', 'vector', 'sparse']
mempalace_drawers: rows=473, fields=['id', 'document', 'metadata', 'vector', 'sparse']
Drawers by room: {'analyzer': 212, 'filter': 156, 'tokenizer': 105}
針對測試中的文件快照,mempalace_drawers 包含 473 行資料,而mempalace_closets 則包含 74 筆內部導覽記錄。衣櫥與抽屜的數量無需一致。抽屜元數據顯示,analyzer 中有 212 個抽屜、filter 中有 156 個,以及tokenizer 中有 105 個。
此檢查會在新的程序中執行,並重新開啟由 CLI 建立的資料庫,這也證實了資料在不同指令間得以保留。
可選:使用 Milvus 伺服器或 Zilliz Cloud
若為共用部署,請在執行相同的 MemPalace CLI 指令前設定 Milvus 連線環境變數。若未設定這些變數,則會使用上文所述的本地 Milvus Lite 資料庫。
若使用 Milvus 伺服器:
export MEMPALACE_MILVUS_URI="http://localhost:19530"
export MEMPALACE_MILVUS_DB_NAME="default"
export MEMPALACE_MILVUS_NAMESPACE="team-memory"
若使用 Zilliz Cloud:
export MEMPALACE_MILVUS_URI="https://your-cluster.api.region.zillizcloud.com"
export MEMPALACE_MILVUS_TOKEN="your-api-key"
export MEMPALACE_MILVUS_DB_NAME="default"
export MEMPALACE_MILVUS_NAMESPACE="team-memory"
本教學中的端到端指令已透過 Milvus Lite 進行驗證。上述伺服器與雲端設定為可選的部署配置,進行本地驗證時並不需要這些設定。
結論
MemPalace 為代理提供了一種結構化的方式來保存專案知識:「翼」將語料庫分隔開來,「房間」提供主題層級的範圍,「抽屜」則保留原始來源文本。 在此範例中,31 頁密切相關的 Milvus 文件頁面,轉化為數百個可搜尋的抽屜,而非僅有幾則手寫記錄。Milvus 透過該結構,提供持久的向量、稀疏資料、文字及元資料儲存功能。