Skip to main content
Glama
doc-search

doc-search

Official
by SodaShikenn

doc-search — 하이브리드 검색 + RAG 채팅 for 문서 리포지토리

사내 문서 리포지토리(용어집·리뷰 관점·설계 문서)를 대상으로 한, 키워드 검색(BM25) × 벡터 검색(의미 검색) 의 하이브리드 검색 엔진과, 그 위에 얹는 RAG 채팅(Claude API·모델 선택·스트리밍 출력).

UI 설계는 SodaShikenn/LLM-RAG_KBQA 를 계승 (왼쪽 사이드바: 모델 선택 / 지식 설정 / 대화 이력, 오른쪽: 채팅 + Send / Cancel).

4가지 사용법:

  1. RAG 채팅 (/) — 모델을 골라 질문. 검색→인용 포함 답변을 스트리밍

  2. 검색 탐색기 (/search.html) — 인크리멘털 검색, KW/VEC/RRF 스코어 표시

  3. CLI — docsearch search "..."

  4. 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.txt

Related 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 vector

API 키가 없어도 모델「Demo(오프라인)」로 채팅 UI 동작 확인이 가능하다.

임베딩 모델 선택 (--embedder)

name

위치

무게

특징

voyage

클라우드

로컬 의존성 제로

voyage-3.5. Anthropic 권장 임베딩 파트너. 품질 최고 클래스. VOYAGE_API_KEY 필요. 문서 텍스트가 외부로 전송되는 점은 승인 필요

e5

로컬

~470MB + torch

multilingual-e5-small. 완전 로컬, 일영 대응의 무난한 기본값

e5-large

로컬

~2.2GB + torch

e5 의 고정밀 버전

bge-m3

로컬

~2.3GB + torch

로컬 최강 클래스의 다국어 모델. 단, 「경량」과는 정반대로 CPU 추론도 느림

hash

로컬

의존성 제로

표기 해시(의미 검색 없음·축퇴 모드)

선택법: 품질과 셋업의 가벼움을 양립하고 싶다면 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)뿐. 실데이터와 사내 리포지토리의 링크는, 액세스 권한이 있는 머신 쪽에서 코드 변경 없이 교체한다. 우선 순위:

  1. 환경 변수(Docker 는 이것): .env 에 DOCSEARCH_DOCS_HOST=/path/to/real-docs(컨테이너로의 마운트 원)와 DOCSEARCH_GITHUB_BASE=https://github.example.com/org/repo/blob/main

  2. 설정 파일(로컬 실행): cp datasource.example.json datasource.json 해서 docs_dir / github_base / embedder 를 편집 → docsearch index(인수 없음). datasource.json 은 gitignore 되어 있고, 사내 리포지토리로의 포인터는 push 되지 않는다

  3. 플레이스홀더: 아무것도 설정하지 않으면 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.plist

  • macOS 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:8765
  • Docker 가 없는 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

Related MCP Servers

  • A
    license
    A
    quality
    D
    maintenance
    MCP server for semantic search across llms.txt documentation sources, with hybrid two-stage retrieval and automatic background refresh.
    5
    MIT
  • A
    license
    Not graded
    quality
    D
    maintenance
    MCP server for documentation search that automatically indexes web documentation sites and provides semantic, full-text, or hybrid search capabilities.
    2 npm
    MIT
  • A
    license
    Not graded
    quality
    A
    maintenance
    MCP server for local RAG over personal notes, PDFs, and documents, enabling plain-English querying and hybrid search with multi-hop context expansion.
    MIT