doc-search
Officialdoc-search — 하이브리드 검색 + RAG 채팅 for 문서 리포지토리
사내 문서 리포지토리(용어집·리뷰 관점·설계 문서)를 대상으로 한, 키워드 검색(BM25) × 벡터 검색(의미 검색) 의 하이브리드 검색 엔진과, 그 위에 얹는 RAG 채팅(Claude API·모델 선택·스트리밍 출력).
UI 설계는 SodaShikenn/LLM-RAG_KBQA 를 계승 (왼쪽 사이드바: 모델 선택 / 지식 설정 / 대화 이력, 오른쪽: 채팅 + Send / Cancel).
4가지 사용법:
RAG 채팅 (
/) — 모델을 골라 질문. 검색→인용 포함 답변을 스트리밍검색 탐색기 (
/search.html) — 인크리멘털 검색, KW/VEC/RRF 스코어 표시CLI —
docsearch search "..."MCP 서버 — Claude Code 의 도구로 등록(Agentic RAG)
셋업(경량: ML 의존 없음·~30MB)
cd doc-search
brew install uv # 未導入の場合
uv venv --python 3.12 .venv
uv pip install -p .venv/bin/python -r requirements.txt
cp .env.example .env # ANTHROPIC_API_KEY を記入(チャット用)로컬 임베딩 모델(e5 / bge-m3)을 쓸 때만, 무거운 ML 스택을 추가:
uv pip install -p .venv/bin/python -r requirements-local.txtRelated MCP server: LLMDoc
사용법
# 1) インデックス構築
.venv/bin/python -m docsearch index sample_docs # 自動選択
.venv/bin/python -m docsearch index /path/to/docs --embedder voyage # クラウド埋め込み
# 2) サーバー起動 → http://127.0.0.1:8765
.venv/bin/python -m docsearch serve --port 8765
# 3) CLI検索
.venv/bin/python -m docsearch search "解約率" --mode vectorAPI 키가 없어도 모델「Demo(오프라인)」로 채팅 UI 동작 확인이 가능하다.
임베딩 모델 선택 (--embedder)
name | 위치 | 무게 | 특징 |
| 클라우드 | 로컬 의존성 제로 | voyage-3.5. Anthropic 권장 임베딩 파트너. 품질 최고 클래스. |
| 로컬 | ~470MB + torch | multilingual-e5-small. 완전 로컬, 일영 대응의 무난한 기본값 |
| 로컬 | ~2.2GB + torch | e5 의 고정밀 버전 |
| 로컬 | ~2.3GB + torch | 로컬 최강 클래스의 다국어 모델. 단, 「경량」과는 정반대로 CPU 추론도 느림 |
| 로컬 | 의존성 제로 | 표기 해시(의미 검색 없음·축퇴 모드) |
선택법: 품질과 셋업의 가벼움을 양립하고 싶다면 voyage(클라우드 허가 시).
완전 로컬 필수라면 e5, 정밀도를 올리고 싶다면 bge-m3(무거움을 허용할 수 있는 경우).
BM25(어형 일치)는 항상 로컬에서 동작하므로, 임베딩의 역할은 「바꿔 말하기」 흡수뿐 —
모델 차이가 효과를 내는 것은 그뿐이고, bge-m3 의 multi-vector/sparse 기능은 이 구성에서는 불필요.
채팅 (RAG) 의 메커니즘
質問 → 検索の深さ(effort)を解決(auto は確信度シグナルで自動判断)
→ 検索実行(hard は選択モデルがクエリを言い換え → 全変種を検索して RRF 融合)
→ system プロンプトに参照資料として注入([n] path:line 付き)
→ Claude API へストリーミング要求(output_config.effort も連動)
→ data: {status|sources|delta|done|error} を SSE 配信
→ UI が逐次描画 + 「なぜこの検索をしたか」の説明 + 引用チップ。会話は localStorage검색의 깊이(effort) — hybrid/keyword/vector 를 숨기기
이용자에게 IR 용어를 선택시키지 않는다. 고르는 것은 「얼마나 제대로 찾을지」뿐이고, 실제로 무엇을 했는지는 답변 아래에 일본어로 표시된다(예: 「자동 → 확실히 — 키워드 일치가 없어…바꿔 말하기를 생성해 깊게 검색」).
effort | 동작 | 사용처 |
자동 (auto) | 한 번 탐색한 뒤 확신도로 easy/medium/hard 를 자동 선택 | 기본값. 고민되면 이것 |
간단 (easy) | 하이브리드 검색 1회·상위 4건. 모델의 effort 도 low | 용어의 직접 검색. 최속·최저가 |
보통 (medium) | 표준 하이브리드 검색·6건 | 종래의 기본 동작 |
확실히 (hard) | 선택 모델이 바꿔 말하기를 3건 생성 → 전체 쿼리로 검색해 RRF 융합·10건. 모델 effort 는 high | 자료와 말투가 다른 질문(예: 「야근한 만큼의 급여」→ 할증 임금) |
auto 의 판단 시그널: 키워드 일치 유무·벡터 유사도의 강함·양쪽 검색의 상위 일치.
바꿔 말하기 생성이 불가능한 경우(Demo 모델·키 미설정)는 hard 를 「건수 확대」로 자동 퇴화.
생 검색 모드(keyword/vector/hybrid)는 엔지니어용으로 /search.html 과 CLI 에 남겨두고 있다.
모델: Claude Opus 5(기본값) / Sonnet 5 / Haiku 4.5 / Demo(오프라인)
Opus 5 는 서버 사이드 refusal fallback 을 유효화(안전상의 답변 거부 시 동일 리퀘스트 내에서 대체 모델로 자동 폴백)
생성 API 는 Anthropic 공식 SDK. 키는
.env의ANTHROPIC_API_KEY
Claude Code 에의 조립(MCP / Agentic RAG)
.mcp.json(대상 리포지토리 또는 홈):
{
"mcpServers": {
"docsearch": {
"command": "/ABSOLUTE/PATH/doc-search/.venv/bin/python",
"args": ["-m", "docsearch.mcp_server"],
"env": { "DOCSEARCH_INDEX": "/ABSOLUTE/PATH/doc-search/index" }
}
}
}도구: search_docs(query, mode, k) / docs_repo_info().
Claude Code 자체가 쿼리 입안→재검색→파일 독해→인용 답변까지 수행하므로,
채팅 UI와는 별도로, 에디터 내에서의 Agentic RAG 가 성립한다.
실데이터로의 교체(액세스 권한이 있는 머신에서)
이 리포지토리에 들어 있는 것은 플레이스홀더(sample_docs)뿐. 실데이터와 사내 리포지토리의 링크는, 액세스 권한이 있는 머신 쪽에서 코드 변경 없이 교체한다. 우선 순위:
환경 변수(Docker 는 이것):
.env에DOCSEARCH_DOCS_HOST=/path/to/real-docs(컨테이너로의 마운트 원)와DOCSEARCH_GITHUB_BASE=https://github.example.com/org/repo/blob/main설정 파일(로컬 실행):
cp datasource.example.json datasource.json해서docs_dir/github_base/embedder를 편집 →docsearch index(인수 없음).datasource.json은 gitignore 되어 있고, 사내 리포지토리로의 포인터는 push 되지 않는다플레이스홀더: 아무것도 설정하지 않으면
sample_docs/를 인덱스
해결 로직은 docsearch/datasource.py 의
get_datasource() 1함수에 집약되어 있다.
인용의 GitHub 링크
검색 결과·인용 칩·답변 중의 [path:line] 는, 문서 리포지토리의
GitHub 상의 해당 행으로의 딥 링크가 된다(blob/<인덱스 시의 SHA>/path#L<line>
형식이므로, 리포지토리가 진행되어도 행 앵커는 어긋나지 않는다).
인덱스 시에 docs 리포지토리의
git remote에서 자동 검출(GHE 도 가능)자동 검출이 불가능한 경우(Docker 로 docs 를 마운트한 경우 등)는
DOCSEARCH_GITHUB_BASE=https://github.com/o/r/blob/main/docs를.env에 설정 (CLI 에서는--github-base)
검색 엔진의 설계 포인트
일본어 키워드 검색: CJK 문자열을 바이그램 전개해 SQLite FTS5 에 인덱스. 쿼리 측은 바이그램의 프레이즈 검색으로 인접 일치(형태소 분석기 없이 동작)
RRF 융합: BM25 스코어와 코사인 유사도는 스케일 비호환 때문에 순위 기반으로 융합
청크에 브레드크럼: 헤딩 계층을 청크 선두에 부여(용어집은 헤딩=용어이므로)
시도하면 재미있는 쿼리
쿼리 | 기대 |
| 키워드로 용어집에 직격 |
| 벡터가 「이탈률」을 발견(바꿔 말하기) |
| 멱등성 / Idempotency-Key 를 인용해 답변 |
| 보안 관점의 테넌트 분리 |
배포
로컬 상주(macOS / LaunchAgent)
bash deploy/install-launchd.sh # ログイン時自動起動・クラッシュ時自動再起動로그:
logs/docsearch.log/logs/docsearch.err.log정지·삭제:
launchctl bootout gui/$(id -u)/com.sodashikenn.docsearch && rm ~/Library/LaunchAgents/com.sodashikenn.docsearch.plistmacOS TCC 주의: 리포지토리가
~/Desktop등의 보호 폴더 아래에 있으면, launchd 기동의 python 이 파일 액세스를 거부당해 기동 루프가 될 수 있다. 그 경우는 「시스템 설정 > 프라이버시와 보안」에서 python 에 액세스 권한을 주거나, 리포지토리를 보호 외(예:~/dev/)로 이동
Docker(다른 머신과의 공유는 이것이 최단)
git clone https://github.com/SodaShikenn/doc-search.git && cd doc-search
cp .env.example .env # ANTHROPIC_API_KEY を記入
docker compose up --build -d # → http://127.0.0.1:8765Docker 가 없는 Mac(Docker Desktop 을 사용하지 않는 경우):
brew install colima docker docker-compose && colima start mkdir -p ~/.docker/cli-plugins && ln -sfn $(brew --prefix)/opt/docker-compose/bin/docker-compose ~/.docker/cli-plugins/docker-compose완전 로컬의 벡터 검색으로 하는 경우(메모리에 여유가 있는 M 시리즈 Mac 권장):
.env에WITH_LOCAL_ML=1과DOCSEARCH_EMBEDDER=e5를 써서docker compose up --build -d(이미지 ~2-3GB, 첫회는 모델 DL 있음. 임베딩 모델의 변경은 기동 시에 검출되어 자동으로 재인덱스)기본의 슬림판 이미지(~300MB): 벡터 검색은
VOYAGE_API_KEY가 있으면 클라우드, 없으면 hash 퇴화(키워드 검색은 항상 풀 동작)실문서는
docker-compose.yml의./sample_docs:/docs:ro를 교체, 내용 갱신 후의 재인덱스는DOCSEARCH_REINDEX=1 docker compose up -d키는 호스트의
.env에서 주입(이미지에는 굽지 않음)인증은 없다. 공개는 로컬 바인드 그대로 리버스 프록시(인증 포함) or VPN 경유로
Third-party
webui/vendor/ 는 자기 호스트한 제3자 라이브러리로, 각자의 라이선스에 따른다:
marked v13.0.2 (MIT)·
DOMPurify 3.1.6 (Apache-2.0 OR MPL-2.0).
그 외는 MIT(LICENSE 참조).
제한과 발전
인덱스는 전체 재구축만(차분 갱신은 미구현)
대화 이력은 브라우저의 localStorage(서버 영속화 없음)
평가: 질문→정답 파일의 recall@k 로 hybrid vs 단체·임베딩 모델 간을 비교하면 좋다
This server cannot be installed
Maintenance
Resources
Unclaimed servers have limited discoverability.
Looking for Admin?
If you are the server author, to access and configure the admin panel.
Related MCP Servers
- AlicenseNot gradedqualityCmaintenanceMCP server for semantic and hybrid search over RHEL documentation using docs2db RAG, with cross-encoder reranking and support for multiple MCP clients.4Apache 2.0
- AlicenseAqualityDmaintenanceMCP server for semantic search across llms.txt documentation sources, with hybrid two-stage retrieval and automatic background refresh.5MIT
- AlicenseNot gradedqualityDmaintenanceMCP server for documentation search that automatically indexes web documentation sites and provides semantic, full-text, or hybrid search capabilities.11MIT
- AlicenseNot gradedqualityBmaintenanceMCP server for local RAG over personal notes, PDFs, and documents, enabling plain-English querying and hybrid search with multi-hop context expansion.MIT
Related MCP Connectors
MCP server for AgentDocs (agentdocs.eu): read, search, write, comment on & share Markdown docs.
Hosted MCP memory: save sessions/decisions once, search from Claude, Cursor, ChatGPT. EU-hosted FTS.
Serve a folder of Markdown notes as an MCP server: hybrid search, reading, and sourced answers.
Latest Blog Posts
- Who's Calling? MCP Hosts Are an Identity Blind Spot (And the Spec Knows It)By Om-Shree-0709 on .mcpAgent IdentityOAuth 2.1
- Your AI Chatbot Just Exposed Your CEO's Salary to an InternBy Om-Shree-0709 on .Agent IdentityMCP SecurityOAuth Delegation
- Why MCP Servers Need Execution Sandboxing (And Why Your Current Stack Isn't Enough)By Om-Shree-0709 on .Agentic AiPrompt InjectionWebAssembly
MCP directory API
We provide all the information about MCP servers via our MCP API.
curl -X GET 'https://glama.ai/api/mcp/v1/servers/SodaShikenn/doc-search'
If you have feedback or need assistance with the MCP directory API, please join our Discord server