Skip to main content
Glama
Eshanya1

sql-specialist-mcp

by Eshanya1

sql-specialist-mcp

SQLite 데이터베이스에 대한 자연어 질문에 답하는 작고 미세 조정된 오픈 가중치 모델로, MCP 도구로 제공되어 모든 MCP 클라이언트(Claude Desktop, Claude Code, 커스텀 에이전트)가 직접 호출할 수 있습니다. 실행 정확도 평가 하네스가 스페셜리스트를 프론티어 모델 프롬프팅과 정확도, 지연 시간, 비용 측면에서 벤치마킹합니다.

이 프로젝트의 요점은 "텍스트-투-SQL 데모 만들기"가 아니라, 프롬프팅 아래에 있는 LLM 엔지니어링의 부분들을 보여주는 것입니다: 작은 모델을 가져와 LoRA로 한 작업에 적응시키고, 효율적으로 서빙하며, 실제 실행 기반 평가를 통해 저렴한 스페셜리스트가 이 좁은 작업에서 프론티어 모델을 프롬프팅하는 것과 경쟁력이 있거나 더 낫다는 것을 증명하는 것입니다.

인터랙티브 데모 사용해보기 — 28개의 실제 평가 질문을 모두 클릭하고 스페셜리스트가 실제로 생성한 SQL, 지연 시간, 결과 행을 프론티어 기준선 옆에서 확인하세요. 설치 불필요.

왜 존재하는가

대부분의 "AI 포트폴리오" 텍스트-투-SQL 프로젝트는 LangChain 퀵스타트입니다. 여기서 두 가지가 다르게 의도되었습니다:

  1. 평가는 엄격하며, 분위기가 아닙니다. 모든 골드 쿼리는 데이터셋 빌드 시점에 데이터베이스에 대해 실행되며(139/139 검증됨), 점수는 쿼리 텍스트가 아닌 결과 집합을 비교합니다 — 열 순서가 다른 의미적으로 올바른 쿼리도 올바른 것으로 채점됩니다. 골드 SQL을 그대로 반환하는 예측기는 100%를, 항상 사소하게 틀린 쿼리를 반환하는 예측기는 0%를 받습니다. 둘 다 정합성 테스트(tests/test_harness_oracle.py)로 체크인되어 하네스 자체의 정확성이 가정되지 않습니다.

  2. 데모 저장소가 아닌 실제 사용 가능한 것으로 제공됩니다. 미세 조정된 모델은 실제 MCP 도구(nl_to_sql)로 노출됩니다 — Claude Desktop 또는 Claude Code를 mcp_server/server.py에 연결하면 대화의 일부로 실제로 데이터베이스를 쿼리할 수 있습니다.

Related MCP server: mcp-sqlite-chat

결과

전체 파이프라인은 실제 하드웨어에서 엔드투엔드로 실행되었습니다: 실제 LoRA 미세 조정, 실제 병합, 실제 GGUF 양자화, 실제 Ollama 서빙, 실제 평가 — 그리고 실제 프론티어 기준선은 라이브 Claude API에 대해 실행되었습니다. 기본 모델: Qwen/Qwen2.5-Coder-0.5B-Instruct (노트북에서 빠른 반복 루프를 위해 선택됨; 미세 조정 아래 1.5B 경로 참조).

예측기

정확도

n

p50 지연 시간

p95 지연 시간

1,000회 호출당 비용

프론티어: Claude Haiku 4.5 (프롬프트됨)

53.6%

28

1055ms

1884ms

$1.06

sql-specialist (미세 조정, 양자화, 로컬)

92.9%

28

207ms

371ms

$0.00

헤드라인뿐만 아니라 주의사항도 함께 읽으세요. 이 평가 세트에 대해 Claude Haiku의 측정된 13개 "실패" 각각을 수동으로 감사했습니다: SQL 논리 오류는 0개였습니다. 13개 모두 열 선택 또는 행 순서 규칙 불일치였습니다 — 예를 들어 골드 답변이 (name)만 요구했는데 (name, email)을 반환하거나, 원래 질문이 실제로 지정하지 않은 ORDER BY와 다른 순서로 올바른 행을 반환하는 경우입니다. 엄격한 실행 정확도 지표(eval/execution.py는 결과 행을 열별로 비교)는 이를 진정으로 잘못된 쿼리와 동일하게 채점하며, 미세 조정된 스페셜리스트는 111개의 훈련 예제에서 이 데이터셋의 정확한 규칙을 암기했기 때문에 그런 쿼리를 생성하지 않습니다 — 제로샷으로 프롬프트된 프론티어 모델이 알 수 없는 것입니다. 실패별 분류는 COMPARISON.md에 전체 있습니다.

따라서: 정확도 격차는 실제이지만 부분적으로 평가가 보상하는 것의 산물이며, 순수한 추론 격차는 아닙니다. 지연 시간과 비용 격차는 산물이 아닙니다 — 207ms/로컬/무료 vs. 1055ms/$1.06-1,000회 호출은 양자화된 0.5B 모델을 로컬에서 실행하는 대신 API를 호출하는 실제 결과이며, 이 프로젝트의 전제가 실제로 의존하는 비교입니다.

스페셜리스트 자신의 2개 실패(28개 중)는 형식 불일치가 아닌 진정한 논리 오류였습니다 — 이 스키마에 존재하지 않는 그럴듯한 orders.total 열을 환각하고, 다중 테이블 SELECT에서 테이블 한정자를 누락했습니다. 훈련은 3 에포크에 걸쳐 깨끗하게 수렴했으며(평가 손실 0.060 → 0.048 → 0.008), 양자화된 모델(988MB f16 → 373MB q4_k_m)은 Ollama를 통해 ~200ms로 서빙됩니다.

여기서 실제인 것

이것을 솔직하게 말하는 것이 보기보다 중요합니다 — 채용 담당자가 신뢰할 수 있는 프로젝트와 마케팅처럼 읽히는 프로젝트의 차이입니다.

  • 합성 데이터베이스와 데이터셋은 증명 가능하게 올바릅니다. shopsphere.db는 결정적으로 시드됩니다(seed=42); data/*.jsonl의 139개 골드 (질문, SQL) 쌍 각각은 매개변수화된 템플릿에서 생성되고 빌드 시점에 실제 데이터베이스에 대해 실행됩니다 — 잘못된 SQL을 생성하는 템플릿은 빌드를 실패시키며, 나쁜 레이블을 조용히 배포하지 않습니다.

  • 평가 하네스의 정확성 자체가 테스트됩니다, 가정되지 않습니다 — tests/test_harness_oracle.py는 오라클 예측기(골드 SQL을 그대로 반환)가 정확히 100%를, 의도적으로 틀린 예측기가 ~0%를 받는지 확인한 후에야 실제 예측기의 숫자를 신뢰합니다.

  • 실행 정확도, 문자열 일치가 아닙니다. eval/execution.py는 결과 집합을 비교합니다(골드 쿼리에 ORDER BY가 없는 한 순서에 무관), 따라서 다르게 작성되었지만 의미적으로 동등한 쿼리는 여전히 올바른 것으로 채점됩니다.

  • 미세 조정은 실제이며, 이 머신에서 실행되었고, 수렴이 검증되었습니다. LoRA(8.8M 훈련 가능 파라미터, 모델의 1.75%) 3 에포크, 평가 손실이 각 에포크마다 단조롭게 감소했습니다. 도중에 발생하고 수정된 두 가지 실제 버그는 엔지니어링 노트를 참조하세요.

  • SQL 실행은 진정으로 샌드박스 처리됩니다, 단지 프롬프트로 행동을 강요하는 것이 아닙니다: 읽기 쿼리는 정규식 허용 목록으로 검증되고 진정한 읽기 전용 SQLite 연결(mode=ro OS 수준)에 대해 실행됩니다 — 정규식 가드의 버그가 쓰기를 초래할 수 없습니다. 이는 평가 하네스 너머에서 중요합니다. 동일한 가드가 MCP 서버에서 실행되며, SQL은 에이전트의 질문에 응답하는 모델에서 나오지, 선별된 평가 세트에서 나오지 않기 때문입니다.

  • MCP 서버는 실제 미세 조정 모델을 서빙하는 실제 호출 가능한 도구입니다, 엔드투엔드로 검증됨: nl_to_sql("Which employees have no manager assigned?") → Ollama를 통해 양자화된 모델로 SQL 생성 → 읽기 전용으로 실행 → 실제 행 반환 → 지연 시간/비용을 관측 가능성에 기록.

  • 관측 가능성은 자체 구축이며 의존성이 없습니다 — observability/logger.py는 모든 호출(지연 시간, 토큰, 예상 비용, 성공/실패)을 로컬 SQLite 파일에 기록하며, 외부 계정이 필요 없고 pr-review-agent와 동일한 패턴입니다.

  • 프론티어 기준선도 실제입니다 — eval/baseline_frontier.py는 라이브 Claude API(Claude Haiku 4.5)에 대해 실행되었으며, 단지 깨끗하게 가져온 것이 아닙니다. 그 "실패"는 실제 평가 방법론 발견을 드러냈습니다 — 결과 위와 COMPARISON.md의 전체 수동 실패 감사를 참조하세요.

엔지니어링 노트: 실제로 실행하면서 발견한 두 가지 실제 버그

미세 조정을 실제로 실행하면("이론상 작동해야 함"으로 남겨두는 대신) 두 가지 실제 PyTorch 메모리 버그가 드러났으며, 둘 다 현재 코드에서 수정되었습니다:

  1. MPS 캐싱 할당자 폭주. Apple Silicon의 MPS 백엔드에서 transformers.Trainer를 통해 훈련하면 동적 배치별 패딩에서 프로세스가 23GB RSS로 부풀어 오르고 멈췄습니다 — 각각의 고유한 (배치, seq_len) 모양은 PyTorch의 MPS 할당자에서 자체 메모리 풀을 얻으며, 해제된 메모리를 OS에 반환하지 않습니다. 수정: finetune.py에서 --device cpu 재정의, 그리고 더 근본적으로 고정 길이 패딩(아래)으로 이 클래스의 버그가 어떤 백엔드에서도 재발할 수 없게 합니다.

  2. Trainer/DataLoader 오버헤드, 모델이 아닙니다. 직접 forward+backward 패스는 1.6초/예제로 측정되었습니다; 동일한 계산을 transformers.Trainer를 통해 실행하면 프로세스가 기록된 단계 사이에 몇 분 동안 유휴 상태로 남아 있었고 해당 계산이 없었습니다. 모델 코드에 버그가 있다고 가정하기 전에 실제 모델+LoRA forward/backward를 수동 타이밍으로 분리하여 근본 원인을 찾았습니다. 수정: Trainer를 ~40줄의 수동 훈련 루프(training/finetune.py)로 대체 — 동일한 LoRA 설정, 배치 루프에 대한 직접 제어, 설명할 수 없는 오버헤드 없음. 또한 배치 콜레이션을 동적 배치별에서 고정 길이 패딩(모든 배치가 동일한 모양)으로 전환했으며, 이는 독립적으로 버그 #1의 할당자 조각화 패턴을 수정했습니다.

두 수정 모두 위에 덧붙인 임시방편이 아닙니다 — 둘 다 training/finetune.py에서 유일한 구현으로 보이며, 대체 경로가 아닙니다.

아키텍처

data/build_dataset.py ──▶ data/{train,eval}.jsonl   (139 examples, template-generated,
                                                       every gold SQL executed at build time)
                              │
        ┌─────────────────────┼─────────────────────┐
        ▼                     ▼                      ▼
training/finetune.py   eval/baseline_frontier.py   tests/test_harness_oracle.py
  (LoRA on a small        (prompt Claude Haiku/       (sanity-checks the harness
   open model)             Sonnet as the baseline)     itself before trusting scores)
        │                     │
        ▼                     │
training/merge_and_quantize.py
        │                     │
        ▼                     ▼
serving/ollama_predictor.py ──┴──▶ eval/harness.py ──▶ eval/report.py ──▶ COMPARISON.md
        │                          (execution-accuracy scoring,
        │                           same logic for every predictor)
        ▼
mcp_server/server.py  (nl_to_sql tool -- installable in Claude Desktop/Code)
        │
        ▼
observability/logger.py  (latency, tokens, cost -- local SQLite, no external account)

프로젝트 구조

schema/           synthetic "ShopSphere" e-commerce DB (7 tables) + seeded generator
data/              templated gold (question, SQL) dataset -- every query build-time validated
eval/              execution-accuracy harness, frontier baseline, comparison report
training/          LoRA fine-tuning pipeline + LoRA-merge/quantize script
serving/           Ollama-backed and in-process HF predictors, Ollama Modelfile template
mcp_server/        the installable MCP tool (nl_to_sql)
observability/     self-built call logging (latency/tokens/cost), no external account
tests/             harness sanity checks (oracle predictor must score 100%)

설정

python3.11 -m venv .venv && source .venv/bin/activate
pip install -r requirements.txt          # base: anthropic, mcp, requests
python schema/generate_data.py           # build the seeded database
python data/build_dataset.py             # build + validate the gold dataset
python tests/test_harness_oracle.py      # confirm the eval harness itself is sound

requirements-train.txt는 미세 조정 경로를 위해 torch/transformers/peft/trl을 추가합니다 — 더 무겁고, 평가/서빙/MCP 경로가 빠르게 설치되도록 분리되어 있습니다.

전체 파이프라인 실행

1. 프론티어 기준선 (ANTHROPIC_API_KEY 필요):

export ANTHROPIC_API_KEY="..."
python -m eval.baseline_frontier --model claude-haiku-4-5
# writes eval/results_claude-haiku-4-5.json

2. 스페셜리스트 미세 조정 (위 결과를 생성하기 위해 실제로 실행된 것 — 노트북 CPU에서 약 15분의 활성 계산이 걸리지만, 벽시계 시간은 시스템 부하에 따라 크게 다릅니다; GPU는 훨씬 빠릅니다, 아래 참조):

pip install -r requirements-train.txt
python -m training.finetune --base-model Qwen/Qwen2.5-Coder-0.5B-Instruct --device cpu
python -m training.merge_and_quantize --base-model Qwen/Qwen2.5-Coder-0.5B-Instruct
# then follow the printed llama.cpp + ollama create instructions

3. 기준선과 동일한 방식으로 스페셜리스트 점수 매기기:

python -c "
from eval.harness import run_eval, report_to_dict
from serving.ollama_predictor import OllamaPredictor
import json
report = run_eval(OllamaPredictor())
json.dump(report_to_dict(report), open('eval/results_specialist.json', 'w'), indent=2)
"

4. 비교 보고서 생성:

python -m eval.report eval/results_claude-haiku-4-5.json eval/results_specialist.json

미세 조정: 확장

위 결과는 빠른 로컬 반복 루프를 위해 CPU에서 Qwen2.5-Coder-0.5B-Instruct를 사용합니다. training/finetune.py --base-model은 모든 HF 인과 언어 모델 저장소(또는 로컬 디렉토리)를 허용합니다 — Qwen2.5-Coder-1.5B-Instruct는 더 나은 품질을 위한 간단한 교체이며, 단일 클라우드 GPU(이 데이터셋 크기에는 T4로 충분)는 ~15분 대신 몇 분 만에 두 크기를 훈련합니다:

pip install -r requirements-train.txt
python -m training.finetune \
  --base-model Qwen/Qwen2.5-Coder-1.5B-Instruct \
  --epochs 3

--device {cuda,mps,cpu}는 자동 감지를 재정의합니다. MPS는 Apple Silicon에서 자동 감지되지만 이 작업에는 아직 권장되지 않습니다 — 엔지니어링 노트 위를 참조하세요.

MCP 서버

# Backend defaults to a locally-served model via Ollama:
python -m mcp_server.server

# Or run against a prompted frontier model instead (no fine-tune needed --
# useful for trying the tool before training anything):
SQL_SPECIALIST_BACKEND=frontier SQL_SPECIALIST_MODEL=claude-haiku-4-5 \
  ANTHROPIC_API_KEY=... python -m mcp_server.server

Claude Desktop의 MCP 구성(claude_desktop_config.json)에 추가:

{
  "mcpServers": {
    "sql-specialist": {
      "command": "/absolute/path/to/sql-specialist-mcp/.venv/bin/python",
      "args": ["-m", "mcp_server.server"],
      "cwd": "/absolute/path/to/sql-specialist-mcp"
    }
  }
}

그런 다음 Claude에게 "Using the sql-specialist tool, which customers have never placed an order?" 같은 질문을 하세요 — nl_to_sql을 호출하고, 데이터베이스에서 실제 행을 가져와 실제 데이터에 기반한 답변을 제공합니다.

보안 노트

  • SQL 실행은 두 개의 독립적인 계층에서 읽기 전용입니다: SELECT/WITH만 허용하는 정규식 가드, 그리고 진정한 OS 수준 읽기 전용 SQLite 연결(file:...?mode=ro)이 백스톱입니다.

  • MCP 서버는 모델이나 호출 에이전트가 무엇을 요청했든 가드가 거부하는 것은 절대 실행하지 않습니다.

  • 이 저장소에는 비밀이 저장되지 않습니다. ANTHROPIC_API_KEY는 환경에서만 읽습니다.

다음에 만들 것

  • 열 상위 집합에 대해 평가 정규화 — 정확한 열별 일치를 요구하는 대신 골드 요청 열의 값이 존재하면 예측을 올바른 것으로 채점합니다. 이는 COMPARISON.md의 실패 분류가 암시하는 수정입니다; 측정된 53.6%→92.9% 격차의 대부분을 닫고 실제 추론 능력을 규칙 일치와 분리하는 비교를 생성할 가능성이 높습니다.

  • eval/baseline_frontier.py를 Claude Sonnet에도 실행하여 더 강한 모델 비교 지점을 확보합니다(Haiku는 저렴/빠른 계층; Sonnet은 "모델 강도만으로 격차를 얼마나 닫는가" 질문).

  • GPU에서 Qwen2.5-Coder-1.5B-Instruct를 미세 조정하고 0.5B 결과(92.9%)와 정확도를 비교하여 크기/품질 트레이드오프를 직접 정량화합니다.

  • 이제 실제 실패 데이터가 있으므로 스페셜리스트의 두 가지 알려진 실패 모드(환각된 열, 다중 조인에서 테이블 한정자 누락)를 대상으로 DPO를 수행합니다.

  • Ollama/GGUF 경로와 처리량 비교를 위한 vLLM 서빙 경로.

Related MCP Connectors

Related MCP Servers

  • F
    license
    Not graded
    quality
    D
    maintenance
    Enables querying and managing a SQLite database using natural language, with an MCP server and Groq LLM.
    -
  • F
    license
    Not graded
    quality
    B
    maintenance
    Enables AI agents to query a SQLite database using natural language through the Model Context Protocol (MCP). Includes security guardrails that block destructive SQL operations.
    -
  • A
    license
    Not graded
    quality
    D
    maintenance
    MCP tool server providing SQLite database access for AI agents.
    MIT