MemPalace 与 Milvus
MemPalace是一个面向编码 Agents 和长期运行的开发工作流的内存层。它将项目知识组织为“翼”、“房间”和“抽屉”,并使原始内容在不同会话间均可搜索。
在本教程中,我们将使用 MemPalace CLI 提取Milvus公开文档中的一部分真实子集,并将其存储在Milvus 中。该语料库包含关于分析器、分词器和令牌过滤器的文档。这些密切相关的页面提供了足够多的干扰项,使检索示例更具实际意义。
本示例使用 Milvus Lite,因此无需 Docker 或单独的数据库服务器即可在本地运行。相同的 MemPalace 配置也可指向 Milvus 服务器或 Zilliz Cloud 以实现共享部署。
先决条件
从 PyPI 安装 MemPalace 及其可选的 Milvus 依赖项。该命令特意未指定具体版本,因此新安装时将自动获取最新可用版本。
uv tool install "mempalace[milvus]"
您还需要 Git 来下载文档语料库。
本教程使用 MemPalace 的本地 MiniLM Embeddings 模型,因此无需外部模型 API 密钥。首次执行挖掘或搜索命令时,可能会下载一个小型 ONNX Embeddings 模型。
配置工作区
创建一个工作区,其中文档和 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 和令牌分别设置为集群的公共端点和 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 文件时不会对其进行摘要或重写,而是计算局部 Embeddings,并将抽屉存储在 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 Collections
MemPalace 会自动管理其 Milvus Schema。要确认存储的内容,请将以下脚本保存为inspect_milvus.py 。该脚本将打开同一 Milvus Lite 数据库,检查 Collections,并按房间统计抽屉数量:
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 为 Agents 提供了一种结构化的项目知识保存方式:“翼”将语料库进行划分,“房间”提供主题级别的范围,“抽屉”则保留原始源文本。 在此示例中,31个密切相关的Milvus文档页面被转化为数百个可搜索的“抽屉”,而非仅有的几条手写记录。Milvus在该结构背后提供了持久的向量、稀疏数据、文本及元数据存储功能。