Transit Functiongemma
БесплатноНе проверенGenerates transit route information by routing user queries to MCP tools using a fine-tuned FunctionGemma model, relying on a fixed API for actual transit data
Описание
Generates transit route information by routing user queries to MCP tools using a fine-tuned FunctionGemma model, relying on a fixed API for actual transit data and avoiding natural language generation beyond tool calls.
README
google/functiongemma-270m-it を乗換案内MCP専用のtool routerとしてLoRA/QLoRA SFTする最小実験環境です。モデルは経路や料金を回答せず、許可されたMCP tool callだけを生成します。経路・料金・所要時間・路線情報は常に https://api.transit.ls8h.com/mcp が返す値を使用します。
構成
scripts/fetch_tools.py: MCPtools/listを取得し、MCP形式とFunctionGemma形式で保存training/prepare_sft.py: synthetic JSONLをFunctionGemmaのmessages/tool_calls形式へ変換training/train_lora.py: fp16、batch size 1、gradient accumulation付きLoRA/QLoRA学習transit_functiongemma/infer.py: 決定的デコードでfunction callを生成scripts/mcp_client.py: callを厳格parse・schema検証後、MCPtools/callを実行evaluation/eval_toolcall.py: 指定された5指標を集計data/raw/synthetic_template.jsonl: 学習データの小さな雛形(本学習前に拡張必須)datagen/generate_synthetic_dataset.py: schema適合済みの拡張train/eval JSONLを決定的に生成datagen/generate_balanced_synthetic_dataset.py: 9 classを均等化したhard-negative付きデータを生成evaluation/analyze_dataset.py: 分布、重複、arguments、token長をJSON/Markdownで分析training/train_lora_plus.py: attention+MLP projectionを選択できる4GB向け追加実験transit_functiongemma/route_normalizer.py: MCP raw resultを事実のみの共通JSONへ正規化transit_functiongemma/route_constraints.py: 経路内の駅を抽出し、avoid/via条件を決定的に検査transit_functiongemma/route_renderer.py: 正規化済みJSONを追加LLMなしで日本語化transit_functiongemma/answer_pipeline.py: router、MCP、正規化、制約検査、rendererを接続transit_functiongemma/local_tools.py: MCPへ送らないローカル疑似tooltransit_functiongemma/station_resolver.py: 路線別IDを物理駅のgeo:地点へ安全に解決
1. サーバーへ配置
モデル、venv、checkpoint、キャッシュは学習サーバー側の作業ディスクに置きます。<server> と /path/to は環境に合わせて読み替えてください。
rsync -av --exclude .venv --exclude outputs ./ <server>:/path/to/transit_functiongemma_mcp/
ssh <server>
cd /path/to/transit_functiongemma_mcp
bash scripts/setup_server.sh
source /path/to/venvs/transit-functiongemma/bin/activate
export HF_HOME=/path/to/huggingface
export XDG_CACHE_HOME=/path/to/cache
export PIP_CACHE_DIR=/path/to/pip-cache
Gemmaの利用規約をHugging Faceで承認し、hf auth login でアクセストークンを設定してください。PyTorch wheelはサーバーのNVIDIA driver/CUDAに合うものを先に入れるのが安全です。
2. schema取得とデータ変換
python scripts/fetch_tools.py
python training/prepare_sft.py --schema-mode baked
拡張データセットを再生成する場合:
python datagen/generate_synthetic_dataset.py --route-groups 80
python training/prepare_sft.py \
--input data/raw/synthetic_generated.jsonl \
--output data/processed/sft_generated.jsonl \
--schema-mode baked
8ツールの完全な宣言は512 tokenを大幅に圧迫するため、既定はschemaを重みに覚えさせる baked です。compact / full も比較用に選べます。学習スクリプトはassistant targetまで512 tokenに収まらないrecordを除外し、全件超過なら停止します。
学習lossはdeveloper/user/tool responseをmaskし、最後のassistant function call(不足情報例では空のassistant turn)だけに適用します。これにより長いpromptの模倣よりtool call構文を優先します。512 token学習とprompt分布を一致させるため、推論も baked が既定です。
raw JSONLの1行は次の形です。駅名は直接 plan_journey に入れず、最初に suggest_stations で解決します。
{"id":"example","reference_datetime":"2026-06-28 09:00 Asia/Tokyo","user":"東京駅を検索","assistant":{"tool_name":"suggest_stations","arguments":{"q":"東京駅","limit":5}}}
不足情報のnegative exampleは "assistant":{"no_tool_call":true} とします。変換後は空のassistant turnとなり、実行側も自然文をMCP callとして扱いません。
3. LoRA学習
GTX 1650 4GB向けの開始設定です。full fine-tune、bf16、batch size増加は実装していません。
python training/train_lora.py \
--dataset data/processed/sft_generated.jsonl \
--output-dir outputs/functiongemma-transit-lora \
--max-seq-length 512 \
--lora-rank 8 \
--epochs 3 \
--gradient-accumulation-steps 16
通常のLoRAでも270Mモデルは小さいため、まず上記を試します。OOM時は指定どおり次へ落とします。
FunctionGemmaの一部RMSNorm重みはGTX 1650上でbase全体をfp16保存するとoverflowするため、通常LoRAは凍結baseをfp32保持し、学習演算をfp16 autocastで行います。fp16 GradScalerは初期scaleを1にしてNaNを防止します。bf16は使用しません。--qlora ではNF4量子化、fp32 norm、fp16 matrix computeを使用します。
python training/train_lora.py --max-seq-length 256 --lora-rank 4 \
--output-dir outputs/functiongemma-transit-lora-r4
さらにbase modelの常駐量を減らす比較実験は --qlora を追加します。GTX 1650とbitsandbytesの組み合わせでは環境依存があるため、LoRAを既定にしています。
4. 推論とMCP実行
python -m transit_functiongemma.infer '東京駅を検索して' \
--adapter outputs/functiongemma-transit-lora
python scripts/mcp_client.py \
--model-output '<start_function_call>call:suggest_stations{q:<escape>東京駅<escape>,limit:5}<end_function_call>'
FUNCTIONGEMMA_CONSTRAINED_DECODE=1 と --constrained-decode を同時に指定すると、推論時に1件のtool callまたはno-callだけを許す最小文法制約をかけます。
FUNCTIONGEMMA_PREFIX_CACHE=1 と --prefix-cache を同時に指定すると、baked modeの固定developer prefixをKV cache化してPyTorch推論のprefillを削減します。
prefixが1 tokenでも一致しない入力では自動的に従来のfull prompt生成へフォールバックします。
scripts/mcp_client.py は次を満たさない出力を実行しません。
- FunctionGemma形式で厳密にparseできる
- 自然文とcallが混在しない
- callがちょうど1件
- tool名が取得済みschemaの許可リスト内
- argumentsがMCPのJSON Schemaに適合
完全なMCP envelopeは artifacts/mcp/ に保存されます。MCP Appsが返す structuredContent、埋め込みresource / resource link、_meta も欠落させず保存します。標準出力の自然文整形はMCP content[type=text] を表示するだけの決定的テンプレートです。
5. 評価
まず付属の正解形式predictionで評価器自体を確認できます。
python evaluation/eval_toolcall.py --predictions data/eval/predictions_example.jsonl
学習済みadapterを直接評価する場合:
python evaluation/eval_toolcall.py --run-model \
--adapter outputs/functiongemma-transit-lora
生成時の余分なresponse tokenを抑える実験は、環境変数とCLIの両方を指定したときだけ有効です:
FUNCTIONGEMMA_CONSTRAINED_DECODE=1 python evaluation/eval_toolcall.py --run-model --constrained-decode ...
PyTorch推論の固定prefix cacheも同様に、FUNCTIONGEMMA_PREFIX_CACHE=1 と --prefix-cache を両方指定したときだけ有効です。
GGUFモデルを既存採点器へ通すには python scripts/generate_gguf_predictions.py --dataset data/eval/sonnet5_holdout_60.jsonl --gguf gguf_work/r8b_Q6_K.gguf --output artifacts/predictions.jsonl でpredictionを作り、
python evaluation/eval_toolcall.py --dataset data/eval/sonnet5_holdout_60.jsonl --predictions artifacts/predictions.jsonl を実行します。
出力指標は parse_success_rate、tool_name_accuracy、required_arguments_satisfaction_rate、datetime_normalization_success_rate、no_call_when_missing_info_rate です。詳細は artifacts/eval_report.json に保存されます。
実運用経路はraw model、表記正規化+schema、実MCP final pipelineを必ず分離して評価します。
python scripts/run_three_stage_evaluation.py \
--adapter outputs/functiongemma-transit-intent-r5 \
--intent-dataset data/eval/operational_intent_raw_100.jsonl \
--final-dataset data/eval/operational_tokyo_routes_100.jsonl
各段階の意味は次の通りです。
- raw model: 元の日本語をFunctionGemmaへ直接入力し、
resolve_route_requestとslotを採点 - normalized: NFKCと空白だけを正規化し、schema-invalid callを拒否して採点
- final pipeline: model slotを駅解決・実Transit MCP・filter/reranker/rendererまで通して採点
追加SFTのdata/raw/operational_intent_train.jsonlとraw holdout
data/eval/operational_intent_raw_100.jsonlは入力文重複ゼロです。前者は駅名を固定
ローテーションした同等表現、後者はユーザー作成の元100件です。
従来protocolの大規模holdoutと手書き実用評価は互換回帰として残しています。
旧regex意味評価を再現するときだけ--legacy-semantic-evalを明示してください。
以下のr4コマンドと2026-06-29実測値は旧beta4回帰記録であり、現行Web配備の
v1.0.0評価値ではありません。
python evaluation/validate_eval_datasets.py
python evaluation/eval_toolcall.py \
--dataset data/eval/independent_holdout_300.jsonl \
--run-model --adapter outputs/functiongemma-transit-ja-real-r4 \
--normalize-ja --schema-constraint \
--output artifacts/eval_independent_holdout_300.json \
--markdown-output artifacts/eval_independent_holdout_300.md \
--failures-output artifacts/failures_independent_holdout_300.jsonl
python evaluation/eval_toolcall.py \
--dataset data/eval/manual_practical_100.jsonl \
--run-model --adapter outputs/functiongemma-transit-ja-real-r4 \
--normalize-ja --schema-constraint \
--output artifacts/eval_manual_practical_100.json \
--markdown-output artifacts/eval_manual_practical_100.md \
--failures-output artifacts/failures_manual_practical_100.jsonl
history付き行は解決済み駅IDを含む会話全体をrouterへ渡します。rawモデルのparse/tool
精度と、表記正規化・schema制約後の精度は分けて記録します。前段はユーザー文から
priority / avoid / via / mode / time_modeを抽出・補完しません。
実Transit MCPを使う固定7シナリオのE2E評価:
python evaluation/eval_pipeline.py \
--adapter outputs/functiongemma-transit-ja-real-r4 \
--clarification-tool \
--max-routes 1
raw envelope、normalized JSON、renderer回答、request/MCP latency、timeout、retryを
artifacts/e2e_*とartifacts/latency_report.jsonへ保存します。
固定7シナリオでは、不足情報をローカルで質問しMCPへ送らないことも評価するため、
--clarification-toolを明示します。
--max-routes 1はレイテンシゲート用にMCPの探索候補数も1件へ制限します。Web UIは
3候補表示を維持します。
2026-06-29の最終実測では、independent_holdout_300はparse/tool/arguments包含/
required/no-call/schemaがすべて100%でした。manual_practical_100はclass/toolとno-callが
100%、intent slot macro F1が97.84%、avoid/viaと日時正規化が100%でした。固定7シナリオの
実MCP E2Eは7/7、p50 1.50秒、p95 4.06秒、timeout 0%、no-call無通信100%、rendererの
source-only検査100%です。詳細は artifacts/eval_independent_holdout_300.md、
artifacts/eval_manual_practical_100.md、artifacts/e2e_eval_report.md を参照してください。
評価器は、現行MCP schemaに存在しない期待引数と、user/historyから観測できない期待値を 件数付きで意味評価から除外します。これはモデルに入力外の値を推測させないためで、raw model指標、schema制約後の指標、除外件数を別々に保存します。
epoch別adapterから外部dev指標でbestを選ぶには python scripts/select_checkpoint.py --run outputs/<run> を使います。GPUなしの配線確認は --dry-run --dev-sample N で行えます。
注意
synthetic_template.jsonl の20件は配線確認用です。通常学習にはschema検証済み470件の synthetic_generated.jsonl を使います。さらなる実験では各tool、言い換え、相対日時、曖昧駅名、誤誘導、required欠落、多段tool responseをtrain/evalで重複しないよう増やしてください。demo-feed:* は学習例内のtool responseから受け取った架空IDであり、実MCPへ送る値ではありません。
tool選択改善用のbalanced実験は NEXT_EXPERIMENT.md を参照してください。ask_clarification は任意のローカル疑似toolであり、scripts/mcp_client.py が必ずMCP送信前に処理します。
旧口語日本語実験の履歴は
JAPANESE_ROUTING_EXPERIMENT.mdを参照してください。
現在の--normalize-jaはNFKCと空白整理だけです。旧intent/slot regexは
semantic_fallback=Trueまたは--legacy-semantic-evalを明示した互換試験と、offlineの
annotation migrationに限定され、productionでは使いません。棚卸しは
artifacts/PARSER_RULE_AUDIT.mdにあります。
以下は旧beta4(旧名r4)実験の記録です。現行Web配備の評価値ではありません。GTX 1650
4GBで口語日本語86件を加えた5 epochのLoRA本学習を完了しました。外部評価は
口語holdout 17件でparse/tool/arguments/no-call/schemaがすべて100%、9 class均等の
corrected eval 72件でparse/tool/no-call/schemaが100%、expected argumentsが81.25%です。
この旧実験のadapterはoutputs/functiongemma-transit-ja-real-r4です。現行v1.0.0の系譜と
評価はリリースmanifestを参照してください。
6. LLMを使わない日本語回答パイプライン
FunctionGemmaは自然文回答モデルではなく、MCP tool callを選ぶrouterとしてのみ使います。
経路、時刻、運賃、路線などの事実はTransit MCPが取得し、transit_functiongemma/route_normalizer.pyが
MCPのraw resultを共通JSONへ変換します。transit_functiongemma/route_constraints.pyは駅IDまたは保守的に
正規化した駅名で回避・経由条件を検査し、transit_functiongemma/route_renderer.pyがそのJSONに存在する値
だけをPythonテンプレートで日本語化します。
後段LLMを置かないのは、MCP結果にない経路・料金・時刻・路線名や、回避条件の成否を
生成モデルが補完してしまう余地をなくすためです。normalizer、constraints、rendererは
ネットワークを使用せず、オフラインで単体テストできます。ネットワークアクセスは
scripts/mcp_client.pyとtransit_functiongemma/answer_pipeline.pyに限定しています。
rendererだけをサンプルJSONで確認:
python -m transit_functiongemma.route_renderer --input data/examples/route_normalized_example.json
python -m transit_functiongemma.route_renderer --input data/examples/station_suggestions_example.json
python -m transit_functiongemma.route_renderer --input data/examples/place_suggestions_example.json
学習済みadapterを使った一連の実行:
export FUNCTIONGEMMA_ADAPTER=outputs/tentetsu-270m-v1.0.0
python -m transit_functiongemma.answer_pipeline "東京駅を検索して"
python -m transit_functiongemma.answer_pipeline "東京タワーを場所として探して"
python -m transit_functiongemma.answer_pipeline "町田から池袋まで、渋谷を避けて" \
--normalize-ja --save-normalized artifacts/normalized --debug
現在のrouterは駅名を直接経路toolへ渡さず、まずsuggest_stationsで解決する段階式です。
経路要求ではtransit_functiongemma/answer_pipeline.pyがそのcallを物理駅解決へ切り替え、suggest_placesの
完全一致駅だけを残し、300m以内の同名Transit/OSM地点を1駅にまとめます。その代表
geo: endpointを多段tool履歴へ戻すため、東海道線・京浜東北線などのfeed IDを経路探索
前に選ぶ必要がありません。「横浜」と「新横浜」、同名の店舗などは一致扱いにしません。
同名の物理駅が離れた場所に複数ある場合だけ利用者へ確認します。
python -m transit_functiongemma.answer_pipeline "横浜から上野までの経路を探して"
python -m transit_functiongemma.answer_pipeline "横浜から上野まで、京浜東北線で行きたい"
「京浜東北線で」のような明示路線は、MCPが返した経路の各legをクライアント側で検査し、 該当候補を優先表示します。サードパーティーMCPの検索条件自体は変更できないため、返却 候補に指定路線がなければ、その範囲では確認できなかったと表示し、経路を捏造しません。
transit_functiongemma/answer_pipeline.pyはrouter出力を厳格parseし、取得済みJSON Schemaで検証してから
MCPを呼びます。空callまたはask_clarificationの場合はMCPを呼ばず確認文を返します。
raw envelopeは既定でartifacts/mcp/へ保存され、--save-normalizedを指定すると正規化
JSONも保存されます。主なオプションは--adapter、--mcp-url、--schema-mode、
--save-raw、--save-normalized、--max-routes、--debugです。
実MCP保存物をオフラインで正規化する場合:
python -m transit_functiongemma.route_normalizer \
--input artifacts/mcp/example_plan_journey.json \
--tool-name plan_journey \
--output artifacts/normalized/example.json
python -m transit_functiongemma.route_renderer --input artifacts/normalized/example.json
7. Web UI
静的UIはサーバーの/var/www/html/transit/に配置し、Apacheの内部プロキシから
127.0.0.1:8091の常駐APIへ接続します。APIは学習済みadapterを一度だけGPUへロードし、
各リクエストで同じToolRouterを再利用します。APIポート自体は外部公開しません。
現行Web APIはoutputs/tentetsu-270m-v1.0.0(Tentetsu-270M v1.0.0)をサーバー上の
PyTorch/PEFT routerとして実行します。iPhoneアプリが端末内で実行するQ6_K GGUFとは
画面上の安全境界を共有しますが、Web版はサーバー推論でありサーバレスではありません。
/api/healthは従来のmodel/readyに加えて、router_release、adapter、
inference_backend=serverを返します。
https://<your-domain>/transit/
サービス確認・再起動:
systemctl --user status transit-functiongemma-web.service
systemctl --user restart transit-functiongemma-web.service
journalctl --user -u transit-functiongemma-web.service -f
実運用behavior log
公開デモ用systemd templateは匿名監査ログだけを有効にし、query hash・文字数・status などの運用指標だけを保存します。ユーザーの検索文、回答本文、raw座標は保存せず、詳細な behavior logも既定で無効です。
同意を得た閉じた検証で数週間の表現揺れ・時刻解釈・tool選択を調べる場合に限り、systemd
unitのTRANSIT_BEHAVIOR_LOG=1を明示的に有効にします。このflagだけではtiming、MCPの
tool名・status・latency・attempt回数などの非本文指標だけを保存します。検索文と入力由来の
router出力・tool引数・intentまで必要な場合はTRANSIT_BEHAVIOR_LOG_USER_QUERY=1を、
回答本文も必要な場合はTRANSIT_BEHAVIOR_LOG_ANSWER=1を個別に指定します。
これらは公開デモの既定値にしません。
有効にしたbehavior logはJSTの日付ごとに次へ保存されます。
artifacts/behavior_logs/YYYY-MM-DD.jsonl
各行はrequest ID、status、応答種別、文字数、MCP tool名とstatus/attempt/latency、全体
latencyを持ちます。TRANSIT_BEHAVIOR_LOG_USER_QUERY=1の場合だけ、入力、router出力、
model_route_intent、deterministic planner step、parsed tool call、schema検証、MCPへ送った
最終引数も追加します。TRANSIT_BEHAVIOR_LOG_ANSWER=1の場合だけ回答本文も追加します。
詳細モードでもlat、lon、geo: endpointと緯度経度文字列は常にマスクし、MCP raw
resultとnormalized route本体はbehavior logへ保存しません。既定保持期間は45日で、
期限切れの日次ファイルは起動時と日付変更後の最初の記録時に削除されます。
# 今日のログを追う
tail -f artifacts/behavior_logs/$(date +%F).jsonl
# サーバーから回収する
rsync -av <server>:/path/to/transit_functiongemma_mcp/artifacts/behavior_logs/ \
artifacts/behavior_logs/
詳細ログはアクセスを制限した検証期間だけ有効にし、終了後は
TRANSIT_BEHAVIOR_LOG_USER_QUERY=0、TRANSIT_BEHAVIOR_LOG_ANSWER=0、
TRANSIT_BEHAVIOR_LOG=0へ戻してください。
都内経路の実運用表現サンプルをまとめて実Web APIへ流す場合:
python scripts/run_operational_samples.py \
--dataset data/eval/operational_tokyo_routes_100.jsonl \
--url http://127.0.0.1:8091/query
結果は artifacts/operational_tokyo_routes.json と
artifacts/operational_tokyo_routes.md に保存されます。HTTP応答だけでなく、behavior logの
モデルのresolve_route_requestと最終MCP引数を参照し、到着/出発、時刻、回避、経由、
優先条件がmodel extractionとexecutionの両段階を通ったかを採点します。元の日本語を
regexで再抽出して正解扱いにはしません。
同名の物理駅が複数ある場合、Web APIは15分間の対話セッションを作り、UIに候補ボタンを
表示します。選択した物理駅のgeo: endpointを保持して元の検索を再開し、目的地も曖昧
なら続けて候補を表示します。候補名・事業者に加えて座標も表示するため、同名駅を区別
できます。セッション情報はメモリ内だけに保持され、完了または期限切れで削除されます。
単独のsuggest_stations / suggest_places結果もボタン表示されます。候補を選ぶと駅IDを
確定して表示し、「出発地にする」「目的地にする」から次の検索文へつなげられます。経路
検索中の駅解決は路線別IDではなく物理駅geo:を使うため、候補選択が利用路線を不必要に
固定することはありません。
構成ファイルはweb/、APIはweb_api.py、systemd unitの原本は
deploy/transit-functiongemma-web.serviceです。
公開運用向けにclient単位rate limit、MCP timeout、指数backoff retry、短期cache、schema
hash変更検知、request ID、匿名監査ログを実装しています。user queryとraw座標の保存は
既定でOFFです。TRANSIT_WEB_SHOW_TRACE=1ではモデル出力、parse済みcall、schema検証、
MCP call、normalized JSON、renderer回答とlatencyを折り畳み表示できます。公開前の残作業は
NEXT_RELEASE_CHECKLIST.mdを参照してください。
Установка Transit Functiongemma
У этого сервера нет опубликованного пакета — он собирается из исходников. Открой репозиторий и следуй инструкции в README.
▸ github.com/sasanokusa/transit_functiongemma_mcpFAQ
Transit Functiongemma MCP бесплатный?
Да, Transit Functiongemma MCP бесплатный — установка в пару кликов через Unyly без оплаты.
Нужен ли API-ключ для Transit Functiongemma?
Нет, Transit Functiongemma работает без API-ключей и переменных окружения.
Transit Functiongemma — hosted или self-hosted?
Доступен hosted-вариант: Unyly запускает сервер в облаке, локальная установка не обязательна.
Как установить Transit Functiongemma в Claude Desktop, Claude Code или Cursor?
Открой Transit Functiongemma на unyly.org, выбери вкладку своего клиента (Claude Desktop, Claude Code, Cursor) и нажми Install — конфиг сгенерируется автоматически, без правки JSON.
Похожие MCP
GitHub
PRs, issues, code search, CI status
автор: GitHubFilesystem
Secure file operations with configurable access controls.
Memory
Knowledge graph-based persistent memory system.
Template MCP Server
A CLI tool to create a new Model Context Protocol server project with TypeScript support, dual transport options, and an extensible structure
автор: mcpdotdirectCompare Transit Functiongemma with
Не уверен что выбрать?
Найди свой стек за 60 секунд
Автор?
Embed-бейдж для README
Похожее
Все в категории development
