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 단체·임베딩 모델 간을 비교하면 좋다
Related MCP Connectors
MCP server for querying Forkast documentation
Self-hosted AI workspace: semantic RAG document search, long-term memory, and AI chat via MCP.
MCP server unifying ERPs, CRMs, APIs and knowledge base for Claude, ChatGPT and Gemini.
Related MCP Servers
- AlicenseNot gradedqualityDmaintenanceMCP 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.2 npmMIT
- AlicenseNot gradedqualityAmaintenanceMCP server for local RAG over personal notes, PDFs, and documents, enabling plain-English querying and hybrid search with multi-hop context expansion.MIT