Milvus와 함께하는 MemPalace

MemPalace는 코딩 에이전트 및 장시간 실행되는 개발 워크플로우를 위한 메모리 레이어입니다. 이 도구는 프로젝트 지식을 '윙(wings)', '룸(rooms)', '서랍(drawers)'으로 체계화한 후, 세션을 넘나들며 원본 콘텐츠를 검색할 수 있게 해줍니다.

이 튜토리얼에서는 MemPalace CLI를 사용하여 공개된 Milvus 문서의 실제 하위 집합을 추출하고 이를 Milvus에 저장해 보겠습니다. 이 코퍼스에는 분석기(analyzers), 토큰화기(tokenizers), 토큰 필터(token filters)에 대한 문서가 포함되어 있습니다. 서로 밀접하게 연관된 이 페이지들은 검색 예제를 의미 있게 만들기에 충분한 방해 요소를 제공합니다.

이 예제에서는 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"

아래 MemPalace 명령어에 --backend milvus 를 전달합니다. 원격 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개의 마크다운 페이지가 포함되어 있습니다. 여기에는 일반적인 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 룸으로 직접 이동합니다.

그런 다음 각 파일은 서로 겹치는 텍스트 청크로 분할됩니다. 모든 청크는 원문 그대로의 마크다운과 wing, room, source_file, chunk_index, 소스 줄 번호와 같은 메타데이터를 포함하는 ‘서랍(drawer)’이 됩니다. 룸과 서랍은 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는 마크다운을 요약하거나 재작성하지 않고 그대로 읽어들이며, 로컬 임베딩을 계산하고 서랍을 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는 에이전트가 프로젝트 지식을 체계적으로 보존할 수 있는 방법을 제공합니다. ‘윙(wing)’은 코퍼스를 구분하고, ‘룸(room)’은 주제 수준의 범위를 제공하며, ‘서랍(drawer)’은 원본 소스 텍스트를 보관합니다. 이 예시에서, 밀접하게 관련된 31개의 Milvus 문서 페이지는 소수의 수기 기록이 아닌 수백 개의 검색 가능한 서랍으로 변환됩니다. Milvus는 이러한 구조의 기반이 되는 벡터, 스파스, 텍스트 및 메타데이터를 지속적으로 저장합니다.