프로젝트 소개
# QMD - 쿼리 마크업 문서
QMD는 개인 지식 기반, 문서, 회의록 및 모든 마크다운 기반 콘텐츠를 위해 설계된 온디바이스 검색 엔진입니다. 완전히 로컬에서 실행되며 BM25 전문 검색, 벡터 의미 검색 및 LLM 기반 재순위화를 결합하여 외부 서비스로 데이터를 전송하지 않고도 고품질 결과를 제공합니다.
## 주요 기능
- **하이브리드 검색 파이프라인**: BM25(FTS5), 벡터 유사성 검색 및 LLM 재순위화를 결합합니다. 쿼리 확장은 적절한 백엔드로 라우팅되는 유형화된 하위 쿼리(`lex` 키워드, `vec` 밀집 벡터, `hyde` 가상 문서 임베딩)를 생성하며, Reciprocal Rank Fusion(RRF)을 통해 융합되고 LLM에 의해 재순위화됩니다.
- **컨텍스트 트리**: 컬렉션에 계층적 컨텍스트를 추가할 수 있습니다(예: `qmd://notes` → "개인 메모 및 아이디어"). 이는 일치하는 문서와 함께 반환되어 LLM이 더 나은 맥락적 결정을 내릴 수 있도록 돕습니다.
- **로컬 모델**: HuggingFace에서 다운로드하여 로컬에 캐시된 GGUF 모델을 사용합니다. 기본 임베딩 모델은 `embeddinggemma-300M-Q8_0`(~300MB)입니다. 사용자 정의 모델은 `QMD_EMBED_MODEL` 환경 변수를 통해 설정할 수 있습니다(예: 다국어 말뭉치용).
- **AST 인식 청킹**: 코드 파일(TypeScript, JavaScript, Python, Go, Rust)에 대해 선택적 tree-sitter 기반 청킹이 더 높은 품질의 청크를 생성하며, 다른 파일 유형은 regex 기반 청킹을 사용합니다.
- **MCP 서버**: 쿼리, 문서 검색, 일괄 검색 및 상태 확인을 위한 도구가 포함된 Model Context Protocol 서버를 노출합니다. stdio 및 HTTP 전송을 지원하며 보안 기능(원본/호스트 검증으로 DNS 리바인딩 공격 방지)이 있습니다.
- **SDK**: 검색, 문서 검색, 컨텍스트 관리 및 쿼리 확장을 위한 메서드가 포함된 TypeScript/JavaScript SDK를 통한 프로그래밍 액세스.
## 빠른 시작
```sh
# 전역 설치 (Node 또는 Bun)
npm install -g @tobilu/qmd
# 또는
bun install -g @tobilu/qmd
# 컬렉션 생성
qmd collection add ~/notes --name notes
qmd collection add ~/Documents/meetings --name meetings
# 컨텍스트 추가
qmd context add qmd://notes "개인 메모 및 아이디어"
# 임베딩 생성
qmd embed
# 검색
qmd search "프로젝트 타임라인" # 빠른 키워드 검색
qmd vsearch "배포 방법" # 의미 검색
qmd query "분기별 계획 프로세스" # 하이브리드 + 재순위화 (최고 품질)
```
## CLI 명령어
- `qmd collection add <경로> --name <이름> [--mask <glob>]` — 컬렉션 추가
- `qmd collection show <이름>` — 컬렉션 세부 정보 표시
- `qmd collection include/exclude <이름>` — 컬렉션 포함 전환
- `qmd collection update-cmd <이름> '<명령>'` — 업데이트 명령 설정
- `qmd embed [--chunk-strategy auto]` — 벡터 임베딩 생성
- `qmd search <쿼리> [-c <컬렉션>] [--json] [--files] [--min-score <n>]` — 키워드 검색
- `qmd vsearch <쿼리>` — 의미 검색
- `qmd query <쿼리>` — 재순위화가 포함된 하이브리드 검색
- `qmd get <경로|문서 ID>` — 문서 검색
- `qmd multi-get <glob>` — 여러 문서 검색
- `qmd mcp [--http] [--port <포트>] [--host <주소>] [--daemon]` — MCP 서버 시작
- `qmd status` — 인덱스 상태 및 MCP 상태 표시
## MCP 서버
노출된 도구:
- `query` — 유형화된 하위 쿼리, RRF 융합 및 선택적 재순위화로 검색
- `get` — 경로, 문서 ID 또는 라인 범위로 문서 검색
- `multi_get` — glob, 쉼표로 구분된 목록 또는 문서 ID로 일괄 검색
- `status` — 인덱스 상태 및 컬렉션 정보
HTTP 전송(기본 포트 8181)은 다음을 제공합니다:
- `POST /mcp` — MCP Streamable HTTP
- `POST /query` (`/search` 별칭) — MCP 프로토콜 없는 구조화된 검색
- `GET /health` — 활성 상태 확인
보안: 비-루프백 `Origin` 헤더가 있는 요청은 거부됩니다(403). `Host` 검증은 DNS 리바인딩을 방지합니다. 환경 변수 `QMD_ALLOWED_ORIGINS` 및 `QMD_ALLOWED_HOSTS`는 허용된 원본/호스트를 확장할 수 있습니다.
## SDK 사용법
```js
const { QmdStore } = require('@tobilu/qmd')
const store = new QmdStore({ dbPath: './qmd.db', collections: { notes: { path: '/path/to/notes' } } })
// 간단한 검색 (자동 확장)
const results = await store.search({ query: 'authentication flow' })
// 유형화된 하위 쿼리가 포함된 구조화된 쿼리
const results2 = await store.search({
queries: [
{ type: 'vec', query: 'why do database connections time out under load' },
{ type: 'lex', query: 'connection timeout' }
],
collections: ['docs', 'notes']
})
// 속도를 위해 재순위화 비활성화
const fast = await store.search({ query: 'auth', rerank: false })
// 메타데이터 필터링
const published = await store.search({
query: 'typescript',
filter: { key: 'topics', operator: 'all', value: ['typescript'] }
})
// 직접 백엔드 액세스
const bm25Results = await store.bm25Search('auth')
const vectorResults = await store.vectorSearch('auth')
// 쿼리 확장
const expanded = await store.expandQuery('auth flow', { intent: 'user login' })
// 문서 검색
const doc = await store.get('docs/readme.md')
const body = await store.getDocumentBody('docs/readme.md', { maxLines: 100 })
// 컨텍스트 관리
await store.addContext('docs', '/api', 'REST API reference documentation')
await store.removeContext('docs', '/api')
```
## 검색 파이프라인 세부 정보
1. **쿼리 확장**: 원래 쿼리(가중치 ×2) + LLM 변형 1개
2. **병렬 검색**: 각 쿼리는 FTS 및 벡터 인덱스 모두를 검색합니다.
3. **상위 순위 보너스**: 어떤 목록에서든 1위 문서는 +0.05, 2-3위는 +0.02를 받습니다.
4. **Top-K 선택**: 재순위화를 위해 상위 30개 후보를 선택합니다.
5. **재순위화**: LLM이 각 문서를 점수화합니다(예/아니오 + logprobs 신뢰도).
점수 범위: 0.0–0.2는 낮은 관련성을 나타내며, 더 높은 값은 더 나은 일치를 나타냅니다.
## 모델 구성
기본 모델:
- 임베딩: `embeddinggemma-300M-Q8_0` (~300MB)
- 재순위화: LLM 기반(요청 시 다운로드)
사용자 정의 임베딩 모델 예시:
```sh
export QMD_EMBED_MODEL="hf:Qwen/Qwen3-Embedding-0.6B-GGUF/Qwen3-Embedding-0.6B-Q8_0.gguf"
```
참고: 임베딩 모델을 변경하면 벡터가 서로 호환되지 않으므로 모든 컬렉션을 다시 임베딩해야 합니다.
## 요구 사항
- Node.js 또는 Bun 런타임
- 모델 및 임베딩을 위한 충분한 로컬 저장 공간
- 선택 사항: 더 빠른 LLM 추론을 위한 GPU/VRAM(모델은 요청 간 VRAM에 유지됨)
## 라이선스
오픈 소스 소프트웨어. 세부 사항은 저장소를 참조하십시오.
Comments
0 Rating appears after 10 ratings
Sign in to join the discussion.