LLMの「なぜその答え?」に答える推論エンジンをRustで作った
注意: これは完成された製品ではなく、アーキテクチャの提案(PoC)です。
はじめに
ChatGPTやClaudeに質問すると、もっともらしい答えが返ってきます。しかし、こう思ったことはないでしょうか。
「その答え、何を根拠に言っているの?」
LLMは回答の根拠が不透明です。ハルシネーション(もっともらしい嘘)を見抜くには、人間が事後的に検証するしかありません。
この問題を解決するために、Mythic Inference Engine を作りました。
※公開準備中です
Mythic Engine とは
GPU不要・決定論的・監査可能な推論エンジンです。LLMを「回答生成器」ではなく**「決裁機関」として扱い、全ての回答に根拠(Evidence)と判断過程(Audit Trail)**を付与します。
"日本の首都は?"
↓
[Mythic Engine]
↓
Decision: ASSERT (信頼度95%)
Response: "日本の首都は東京です。"
Evidence: geo-001 (Knowledge Base, score: 0.80)
Audit: S1→S2→S3→...→S10(ASSERT)→S12→S13
従来のLLM APIとの違いを表にまとめます。
| 従来のLLM API | Mythic Engine | |
|---|---|---|
| 根拠 | 不透明 | Evidence付きで明示 |
| 判断過程 | ブラックボックス | 13状態マシンで全記録 |
| 再現性 | 温度パラメータに依存 | JCS+SHA-256で決定論的ハッシュ |
| 判断の種類 | 「回答」のみ | Assert/Hedge/Ask/Refuse/Defer |
| GPU | 必須 | 不要(Rustコアはコアはで動作) |
なぜ作ったのか
LLMは便利ですが、業務判断に使おうとすると壁にぶつかります。
- 「なぜこの判断をしたのか」を説明できない
- 判断の正しさを第三者が検証できない
- 同じ質問でも毎回違う答えが返る可能性がある
医療、法務、金融などの領域では「答えが正しいかどうか」以上に「なぜその答えに至ったか」が重要です。Mythic Engineはこの「なぜ」を構造化して記録します。
RAGや既存OSSとの違い
RAGとはレイヤーが違う
RAG(Retrieval-Augmented Generation)は「関連情報を検索してLLMに渡す」仕組みで、回答の品質を上げる手段です。Mythic Engineは、その回答に対して「本当に断言してよいのか」を判断し記録する決裁・監査の仕組みです。
RAG: 質問 → 検索 → LLMに渡す → 回答
Mythic Engine: 質問 → 検索 → 証拠評価 → 判断(5種類) → 監査ログ付き回答
競合ではなく、RAGの上に組み合わせられる関係です。
既存OSSとの比較
LLMの出力を制御するOSSとしては Guardrails AI や NeMo Guardrails が知られていますが、それぞれ目的が異なります。
| 特徴 | Guardrails AI | NeMo Guardrails | Mythic Inference Engine |
|---|---|---|---|
| 主目的 | 構造検証 (JSON, SQL) | 対話制御 (安全性, 逸脱防止) | 説明責任・監査 (根拠, ログ) |
| 制御対象 | 出力フォーマット・データ品質 | 会話の流れ・トピック | 推論プロセスそのもの |
| アプローチ | バリデータによる事後チェック | ガイドレールによる誘導 | ステートマシンによる決定論的処理 |
| 判断の根拠 | ルール適合性 | セーフティポリシー | Evidence (証拠) |
| 実装言語 | Python | Python | Rust (GPU不要・バイナリ) |
Guardrails AI は「出力が正しいフォーマットか」、NeMo Guardrails は「会話が安全な範囲に収まっているか」をチェックします。Mythic Engine は「なぜその答えに至ったか」を証拠と共に記録し、判断に自信がなければ断言しないという、説明責任と監査可能性にフォーカスしています。
アーキテクチャ
全体像
Mythic EngineはRust製のシングルバイナリです。v0.12でPython依存を完全に排除し、LLMとの通信もRustから直接行います。
┌─────────────────────────────────────────────────┐
│ Mythic Engine (Rust / axum) │
│ │
│ ┌────────────────────────────────────────────┐ │
│ │ API Layer │ │
│ │ REST / SSE / JSON-RPC 2.0 │ │
│ └────────────────────────────────────────────┘ │
│ ┌────────────────────────────────────────────┐ │
│ │ 13-State Machine (推論コア) │ │
│ │ Receive → Freeze → ... → Decide → Emit │ │
│ └────────────────────────────────────────────┘ │
│ ┌──────────┐ ┌──────────┐ ┌───────────────┐ │
│ │ Evidence │ │ LLM │ │ Audit Log │ │
│ │ Retrieval │ │ Provider │ │ (SQLite) │ │
│ └──────────┘ └──────────┘ └───────────────┘ │
└─────────────────────────────────────────────────┘
│ │
▼ ▼
Knowledge Base LLM APIs
(JSON) (vLLM/Gemini/OpenAI/Ollama/DeepSeek)
13-State Machine
Mythic Engineの心臓部は13の状態を持つステートマシンです。入力から出力まで、全てのステップが明示的に定義されています。
S1: Receive 入力を受け取る
S2: Freeze JCS正規化 + SHA-256ハッシュで入力を固定
S3: Translator 自然言語 → IntentEnvelope(構造化された意図)に変換
S4: Taboo 禁忌ルールチェック(危険な質問をブロック)
S5: Sanity 入力品質チェック(曖昧すぎないか等)
S6: InvocationDecide どのプロバイダを呼ぶか決定
S7: Invoke 証拠収集(Knowledge Base / Web検索 / Vector検索)
S8: Check 収集結果の検証
S9: Merge 複数ソースの証拠を統合
S10: Decide 証拠に基づき判断(Assert/Hedge/Ask/Refuse/Defer)
S11: Genealogy 証拠の系譜グラフを構築
S12: Emit 結果を出力
S13: End 処理完了
ポイントは S2: Freeze です。入力をJSON Canonicalization Scheme (JCS, RFC 8785) で正規化し、SHA-256でハッシュ化することで、同じ入力に対して常に同じハッシュが得られます。これにより再現性と改ざん検知が可能になります。
もう一つの重要なステップが S3: Translator(意図解析) です。ユーザーの自然文をLLMに渡し、エンジンが処理できる構造化データ(IntentEnvelope)に変換します。
入力: "日本の首都は?"
↓ LLMが意図を解析
{
"goal": "日本の首都を知りたい", // 目的(簡潔に整理)
"keywords": ["日本", "首都"], // 根拠検索用キーワード
"task_type": "qa" // 質問の種類
}
このキーワードを使って後続のS7(証拠収集)でKnowledge Baseを検索し、見つかった証拠の信頼度に基づいてS10(判断)で5種類の決裁を下します。
1つの質問に対して最高で2回LLMを呼び出す構造になっています(S3の意図解析と、S10以降の応答生成)。
5つの判断タイプ
LLMは「回答する」か「回答しない」の二択ですが、Mythic Engineは5種類の判断を下します。
| 判断 | 意味 | いつ使われるか |
|---|---|---|
| Assert | 断言 | 信頼度80%以上の証拠がある |
| Hedge | 推測 | 証拠はあるが信頼度が50-80% |
| Ask | 質問 | 情報が足りないので聞き返す |
| Refuse | 拒否 | 禁忌ルールに抵触 |
| Defer | 保留 | 証拠が不十分で判断できない |
これにより、「自信がないのに断言する」というLLMの典型的な問題を構造的に防ぎます。
独自Knowledge Base(辞書)
Mythic Engineが回答の根拠として参照する知識ベースは、自由に追加できます。社内ナレッジや製品情報など、独自の辞書を構築してEvidence(証拠)として活用できます。
CSVで辞書を作成し、付属の変換ツールでJSONに変換するのが最も簡単です。
id,content,source_uri
product-001,"製品Aは月額1000円で利用できます。",料金表
policy-001,"返品は購入から30日以内に受け付けます。",https://example.com/policy
faq-001,"営業時間は9:00〜18:00です。",FAQ
# CSV → JSON変換(バリデーション付き)
python tools/csv2knowledge.py knowledge/my_data.csv
# バリデーションのみ(変換せず確認だけ)
python tools/csv2knowledge.py knowledge/my_data.csv --validate-only
変換ツールはUTF-8 BOMの自動除去、重複IDの検出、空行のスキップなど、実運用で起きがちな問題を自動的に処理します。
生成されたJSONを起動時に指定するだけで、エンジンがキーワードマッチやベクトル検索で関連エントリを見つけ出し、回答の証拠として提示します。
エントリ数の目安: Knowledge BaseはJSON全件をメモリにロードし、キーワードで線形検索します。数千件程度であれば問題なく動作します。1万件を超える規模のデータには、ベクトル検索(Vector Search)の利用を推奨します。
./target/release/mythic-engine serve \
--knowledge ./knowledge/my_data.json
技術スタック
| 領域 | 技術 |
|---|---|
| 言語 | Rust (Edition 2021) |
| Webフレームワーク | axum 0.7 |
| 非同期ランタイム | tokio |
| シリアライズ | serde + serde_json |
| ハッシュ | serde_jcs (JCS) + sha2 (SHA-256) |
| LLM統合 | genai crate |
| DB | SQLite (Diesel ORM) |
| ストリーミング | Server-Sent Events (SSE) |
使ってみる
セットアップ
git clone https://github.com/cosmopanda432/mythic-engine.git
cd mythic-engine
cargo build --release
LLMプロバイダの設定
config/server.yaml でLLMプロバイダを選択します。ローカルLLM(vLLM, Ollama)とクラウドAPI(Gemini, OpenAI, DeepSeek)の両方に対応しています。
llm:
provider: gemini # vllm | gemini | openai | ollama | deepseek
gemini:
model: "gemini-2.0-flash"
# Geminiの場合
export GEMINI_API_KEY=your-api-key
サーバー起動
./target/release/mythic-engine serve \
--config ./config/server.yaml \
--knowledge ./knowledge/demo.json \
--rules ./rules
ブラウザで http://localhost:8082/ を開くとWeb UIが使えます。
APIで問い合わせ
Mythic Engineは用途に応じて複数のAPIメソッドを提供しています(mythic.ask / llm.chat / mythic.run / mythic.translate)。Web UIやREST APIからは全自動の mythic.ask が使われます。各メソッドの違いや使い分けについては READMEのAPIリファレンス を参照してください。
curl -X POST http://localhost:8082/api/v1/ask \
-H "Content-Type: application/json" \
-d '{"text": "日本の首都は?"}'
レスポンスには判断・証拠・監査ログが含まれます。
{
"success": true,
"decision": {
"decision_type": "assert",
"confidence": 0.95
},
"generated_response": "日本の首都は東京です。",
"evidence": [
{
"id": "geo-001",
"source": "knowledge",
"score": 0.80,
"content": "日本の首都は東京である"
}
],
"trace_id": "req-abc123"
}
SSEストリーミングにも対応しており、リアルタイムで状態遷移を確認できます。
curl -N -X POST http://localhost:8082/api/v1/ask/stream \
-H "Content-Type: application/json" \
-d '{"text": "日本の首都は?"}'
設計上のこだわり
1. LLMを「決裁機関」として扱う
Mythic EngineはLLMに「答えを生成させる」のではなく、集めた証拠に基づいて「判断を下す」役割を与えています。LLMは裁判官のように、証拠を見て「断言できる」「推測にとどまる」「判断を保留する」といった決裁を行います。
2. GPU不要
推論エンジンのコア(13状態マシン、証拠照合、判断ロジック)はRustで書かれており、GPUは不要です。LLMの呼び出しは外部API経由で行うため、エンジン自体はCPUのみで動作します。
3. 全過程を監査可能
全ての状態遷移がSQLiteに記録されます。「いつ、どの証拠を使って、なぜその判断に至ったか」を事後的に追跡できます。
4. Python依存の排除
v0.11まではPython製のMCPサーバーがLLMとの仲介役でしたが、v0.12で genai crateを導入し、Rust単体で完結するアーキテクチャに移行しました。デプロイがシングルバイナリで済むようになり、運用が大幅に簡素化されました。
開発の経緯
| Version | マイルストーン |
|---|---|
| v0.1 | 13状態マシンとAudit Trailの基盤 |
| v0.2-v0.5 | 証拠取得層(ファイル検索、ベクトル検索) |
| v0.6 | Web UI + HTTP API |
| v0.7-v0.8 | Web検索統合、Evidence Ranking |
| v0.9-v0.10 | LLMプロバイダ統一、SSEストリーミング |
| v0.11 | JSON-RPC 2.0、API Key認証 |
| v0.12 | Python MCP Server廃止 → Rust直接統合 |
| v0.13 | SQLite監査ログ (Diesel ORM) |
13バージョンで、「ステートマシンだけの実験コード」から「Web UI・複数LLM・ストリーミング・監査ログを備えた推論エンジン」に育ちました。
今後の展望
- Evidence Graph: 証拠間の関係性をグラフ構造で表現し、弁証法的な推論を可能にする
- v1.0安定版: ドキュメント整備とAPIの安定化
まとめ
Mythic Inference Engineは「LLMに根拠と説明責任を持たせる」ための推論エンジンです。
- 全ての回答に**証拠(Evidence)**を紐付け
- 全ての判断を13状態マシンで構造化
- 全ての過程を監査ログに記録
- 5種類の判断で「自信がないのに断言する」問題を防止
- GPU不要、Rustシングルバイナリで動作
※公開準備中です
ライセンス
Apache License 2.0
作者
cosmopanda
貢献
これは研究用のプロトタイプです。
謝辞
Mythic Engineは以下のOSSに支えられています。
Discussion