Skip to main content
Glama
Eshanya1

sql-specialist-mcp

by Eshanya1

sql-specialist-mcp

SQLiteデータベースに関する自然言語の質問に回答する、小型でファインチューニング済みのオープンウェイトモデル。MCPツールとして提供され、任意のMCPクライアント(Claude Desktop、Claude Code、カスタムエージェント)から直接呼び出せます。さらに、実行精度を検証する評価ハーネスを備え、このスペシャリストをフロンティアモデルへのプロンプティングと精度・レイテンシ・コストの観点でベンチマークします。

このプロジェクトの狙いは「text-to-SQLデモを作る」ことではありません。LLMエンジニアリングのうち、プロンプティングより下位に位置する部分、つまり小さなモデルをLoRAで一つのタスクに適応させ、効率的にサーブし、実行ベースの本物の評価で「安価なスペシャリストが、この狭いタスクではフロンティアモデルへのプロンプティングと互角(あるいはそれ以上)である」ことを示すことです。

インタラクティブデモを試す — 28問すべての実評価問題をクリックして、スペシャリストが実際に生成したSQL、レイテンシ、結果行をフロンティアベースラインと並べて確認できます。インストール不要です。

なぜこれを作ったか

「AIポートフォリオ」系のtext-to-SQLプロジェクトのほとんどはLangChainのクイックスタートです。ここで違うのは次の2点です。

  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(ノートPCでの高速な反復ループを選定。ファインチューニングの1.5Bパスを参照)。

予測器

精度

n

p50レイテンシ

p95レイテンシ

コスト/1kコール

フロンティア: Claude Haiku 4.5(プロンプト)

53.6%

28

1055ms

1884ms

$1.06

sql-specialist(ファインチューニング済み、量子化済み、ローカル)

92.9%

28

207ms

371ms

$0.00

これは見出しだけでなく、注意書きも読んでください。 Claude Haikuの13件の測定された「失敗」をすべて手動で監査しました。SQLロジックエラーはゼロでした。 13件すべてが列選択または行順序の規約不一致でした。たとえば、ゴールドが(name)だけのところを(name, email)を返す、あるいは元の質問が実際には指定していないORDER BYと異なる順序で正しい行を返す、などです。厳密な実行精度メトリクス(eval/execution.pyは結果行を列ごとに比較)は、これらを真に誤ったクエリと同一にスコアリングします。ファインチューニング済みスペシャリストは、111件のトレーニング例からこのデータセットの正確な規約を記憶しているため、そのような誤りは決して生成しません。ゼロショットでプロンプトされたフロンティアモデルには知る術がないことです。失敗の分類の詳細はCOMPARISON.mdにあります。

つまり、精度ギャップは実在しますが、その一部は評価が報酬を与えるものの産物であり、純粋に推論ギャップではありません。 レイテンシとコストのギャップは産物ではありません — 207ms/ローカル/無料 vs. 1055ms/$1.06/1kコールは、量子化された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エポック、評価損失は各エポックで単調減少。途中で遭遇し修正した2つの実バグについてはエンジニアリングノートを参照。

  • SQL実行は本当にサンドボックス化されており、振る舞いを促すだけではない。 読み取りクエリは正規表現の許可リストで検証され、さらに真の読み取り専用SQLite接続(OSレベルでmode=ro)に対して実行されます。正規表現ガードのバグがあっても書き込みは発生しません。これは評価ハーネスを超えて重要です。同じガードが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)に対して実行されました。単にクリーンにインポートされただけではありません。その「失敗」は実際の評価方法論の発見を明らかにしました — ResultsとCOMPARISON.mdの完全な手動失敗監査を参照してください。

エンジニアリングノート: 実際に実行して見つけた2つの実バグ

ファインチューニングを実際に実行すると(「理論上は動くはず」のままにせず)、2つの本物のPyTorchメモリバグが浮上し、両方とも現在のコードで修正されています。

  1. MPSキャッシングアロケータの暴走。 Apple SiliconのMPSバックエンドでtransformers.Trainerを介してトレーニングすると、動的なバッチごとのパディングでプロセスが23GBのRSSに膨らみ、ハングしました。各異なる(batch、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因果LMリポジトリ(またはローカルディレクトリ)を受け入れます。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で自動検出されますが、このタスクにはまだ推奨されません — Engineering Notesを参照してください。

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に「sql-specialistツールを使って、注文を一度もしたことがない顧客は誰ですか?」のような質問をします。nl_to_sqlを呼び出し、データベースから実際の行を取得し、実際のデータに基づいて回答します。

セキュリティノート

  • SQL実行は2つの独立した層で読み取り専用です: 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%)と精度を比較して、サイズ/品質のトレードオフを直接定量化する。

  • 実際の失敗データが存在するようになったので、スペシャリストの既知の2つの失敗モード(幻覚列、マルチジョインでのテーブル修飾子の欠落)を対象とした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