ワンクリックで
bm25-search
BM25 Okapi 알고리즘을 사용하여 법령/판례 API 결과를 관련도 순으로 재랭킹합니다. search_enhance_tools.py와 bm25_search.py 구현 시 참조.
Codex または Claude でインストール この Prompt をコピーして Codex、Claude、または他のアシスタントに貼り付けると、Skill ページを確認してインストールできます。
メニュー
BM25 Okapi 알고리즘을 사용하여 법령/판례 API 결과를 관련도 순으로 재랭킹합니다. search_enhance_tools.py와 bm25_search.py 구현 시 참조.
Codex または Claude でインストール この Prompt をコピーして Codex、Claude、または他のアシスタントに貼り付けると、Skill ページを確認してインストールできます。
SOC 職業分類に基づく
법령/판례 캐시 데이터 관리 시 사용. 캐시 저장/로드, 만료 처리, 지식 그래프 동기화. 성능 최적화 및 API 호출 최소화를 위해 캐싱 구현 시 참조.
법제처 OPEN API를 MCP 프로젝트에 통합할 때 사용. lawSearch.do와 lawService.do 엔드포인트, target 파라미터로 기능 구분. 새로운 API 엔드포인트 통합 시 참조.
도구 실패/API 오류 발생 시 4단계 근본 원인 분석 후 수정. 증상 수정이 아닌 원인 수정. superpowers의 systematic-debugging 기반.
새 도구 개발 또는 버그 수정 시 실패하는 테스트를 먼저 작성하고, 구현 후 통과를 확인. superpowers의 test-driven-development 기반.
도구 개발/개선 완료 선언 전 반드시 실제 API 호출 테스트를 수행하고 증거를 기록할 때 사용. superpowers의 verification-before-completion 기반.
Tool에서 API 호출 시 컨텍스트 처리. streamable-http와 stdio transport 모두 지원. with_context() 패턴으로 전역 컨텍스트 fallback 자동 처리.
| name | bm25-search |
| description | BM25 Okapi 알고리즘을 사용하여 법령/판례 API 결과를 관련도 순으로 재랭킹합니다. search_enhance_tools.py와 bm25_search.py 구현 시 참조. |
search_law가 더 빠름)사용자 쿼리
│
▼
법제처 API (법령명 기반 검색, top-50)
│
▼
BM25 재랭킹 (bm25_search.py)
- 토크나이저: 공백/구두점 분리, 불용어 제거, 2자 이상 토큰
- BM25Okapi 계산 (rank-bm25 패키지)
- 점수 기준 내림차순 정렬
│
▼
상위 K개 반환 (각 항목에 _bm25_score 추가)
from mcp_kr_legislation.utils.bm25_search import rank_search_results, BM25Ranker
# 간단 사용
ranked = rank_search_results(
query="개인정보 처리 동의",
results=api_results,
text_keys=["법령명한글", "소관부처명"],
top_k=10,
)
# 세부 제어
ranker = BM25Ranker()
ranked = ranker.rank(
query="손해배상 과실상계",
documents=precedents,
text_keys=["사건명", "법원명"],
top_k=5,
score_threshold=0.1, # 최소 점수 필터
)
| 도구 유형 | text_keys |
|---|---|
| 법령 | ["법령명한글", "소관부처명", "법령구분명"] |
| 판례 | ["사건명", "법원명", "사건종류명"] |
| 위원회결정문 | ["사건명", "결정유형명"] |
| 행정규칙 | ["법령명", "소관부처명"] |
| 법령용어 | ["법령용어명", "뜻풀이"] |
# search_enhance_tools.py에 추가
@mcp.tool(name="search_legal_term_bm25", ...)
def search_legal_term_bm25(query: str, top_k: int = 10) -> TextContent:
cache_key = get_cache_key(f"bm25_lstrm_{query}_50", "bm25")
cached = load_from_cache(cache_key)
if not cached:
data = _raw_search("lstrm", query, display=50)
items = _extract_list(data, "LstrmSearch")
save_to_cache(cache_key, items)
else:
items = cached
ranked = rank_search_results(
query, items,
text_keys=["법령용어명", "뜻풀이"],
top_k=top_k
)
# 포맷팅 후 반환
| 기능 | 현황 | 개선 방향 |
|---|---|---|
| 토크나이저 | 공백 분리 | kiwipiepy 형태소 분석 |
| 문서 본문 검색 | 법령명만 | 조문 내용 포함 |
| 의미 기반 검색 | 미구현 | sentence-transformers 추가 |
| 하이브리드 검색 | 미구현 | BM25 + 벡터 결합 |
# pyproject.toml
dependencies = [
"rank-bm25>=0.2.2", # BM25Okapi 구현
]
rank-bm25 없으면 자동으로 TF 폴백 사용 (성능 저하 있음).
src/mcp_kr_legislation/utils/bm25_search.py — 핵심 구현src/mcp_kr_legislation/tools/search_enhance_tools.py — MCP 도구.cursor/rules/20-bm25-search-guide.mdc — Cursor 룰