はじめに
RAG(Retrieval-Augmented Generation)は企業のAI活用における事実上の標準になりました。しかし、RAGには構造的な限界があります。
- 検索精度がembeddingの質に依存する — 質問の言い回しが変わると、同じ事実にたどり着けない
- 再埋め込みコストが高い — 文書が更新されるたびにベクトルDBの再構築が必要
- 時系列情報を保持できない — 「2023年のbaud rateは9600だったが、2024年に19200に変更された」という変遷を扱えない
- 知識の説明性が低い — なぜその回答に至ったかを構造的に説明できない
本記事では、これらの課題に対する実験的なアプローチとして KRF(Knowledge Runtime Format) を提案します。KRFは「AIが検索するのではなく、AIがそのまま知識として利用する実行形式」を目指すフォーマットです。
前回の記事 「社内サーバーの10TBをAIの知識にする ― 外部重みアーキテクチャとAdaptive Knowledge Depthの提案」 では、LLMの知識を W_static(内部重み) と W_external(外部重み) に分離し、企業のファイルサーバーを「外部重み」として設計に組み込むアーキテクチャを提案しました。そこでは Directory Router や Hierarchical File Attention といった探索設計を論じましたが、W_external の具体的なデータフォーマットには踏み込んでいませんでした。
本記事はその続編として、W_external を実現するための 具体的な知識フォーマットとランタイム を実装し、計測データで検証します。
本記事のスタンス: KRFは「次世代標準」ではなく、企業知識をAI向けにコンパイルする実験的な知識ランタイム形式として位置づけています。RAGを否定するものではなく、RAGが苦手な領域を補完する可能性を実験的に検証するものです。
対象読者
- RAGを運用していて限界を感じているエンジニア
- 社内文書のAI活用を検討しているインフラ・情報システム担当者
- 知識グラフやセマンティック技術に関心のある技術者
この記事で扱う内容
- KRFの設計思想とアーキテクチャ
- 製造業の不具合報告書30件を対象としたプロトタイプ実装
- KRF vs RAG(TF-IDFベース)のスケールベンチマーク
- 計測データに基づく考察と限界の明示
環境
- OS: Ubuntu 24.04(WSL2)
- CPU: Intel Core i9-9900K
- Python: 3.12.3
- GPU: 不使用(全処理CPU完結)
- 依存: networkx(グラフ構造)、標準ライブラリのみ
KRFの設計思想
RAGのパイプライン
Document → Chunking → Embedding → VectorDB → Search → LLM
RAGでは、質問が来るたびにベクトル検索を行い、関連するチャンクを取得してLLMに渡します。このパイプラインには「検索」という非決定的なステップが含まれています。
KRFのパイプライン
Document → Knowledge Compiler → KRF Package → Runtime Lookup → LLM
KRFでは、文書を事前に「知識」にコンパイルし、entity指定のクエリに対してはハッシュマップベースのO(1)ルックアップで必要な知識を取得します。ただし、自由文クエリについてはentity特定が必要であり、この部分は未解決です(後述)。
前回記事の用語で整理すると、KRFは以下の位置づけになります。
W_external の実装方式:
├─ RAG(検索ベース) ... ベクトル類似度で関連チャンクを検索
├─ SQL / API ... 構造化データへの問い合わせ
└─ KRF(コンパイルベース) ... 事前に知識グラフへ変換し、直接アクセス ← 本記事
前回記事で提案した Directory Router → Hierarchical File Attention → LLM のパイプラインでは、最終段の「ファイル内容をLLMに渡す」部分でRAGのチャンク検索が使われます。KRFはこの最終段を、検索ではなくルックアップに置き換える提案です。
Knowledge Unit
KRFの最小単位は Knowledge Unit です。
knowledge_id: K000145
entity: ProductA
relation: cause
value: 電源回路のデカップリングコンデンサのESR劣化により高周波ノイズが伝搬
confidence: 0.94
valid_from: 2024-01-15
valid_to: null
source_report: DR-2024-001
tags: [defect, cause]
Knowledge Unitは(entity, relation, value)のトリプルに、信頼度・時間範囲・出典を付加したものです。RAGのチャンクが「テキストの断片」であるのに対し、Knowledge Unitは構造化された事実です。
KRF Package構成
package.krf/
├─ manifest.json # メタデータ
├─ index # entity → Knowledge Unit のハッシュマップ(entity指定時O(1))
├─ graph # entity間の関係グラフ(NetworkX DiGraph)
└─ temporal # entity|relation → [(date, value)] の時系列インデックス
既存研究との関係
KRFの各要素は、いずれも既存の研究領域に対応しています。KRFは未知の技術ではなく、既存技術を「Knowledge Compiler → Runtime」として統合した設計に独自性があります。
| KRFの要素 | 対応する既存研究・技術 |
|---|---|
| Knowledge Unit(entity, relation, value) | Knowledge Graph、RDF Triple、Property Graph |
| Temporal Layer(valid_from / valid_to) | Temporal Knowledge Graph |
| lookup() | Key-Value Memory(MANN等) |
| graph探索 | GraphRAG(Microsoft, 2024) |
| Knowledge Compiler | Information Extraction、NER + Relation Extraction |
| Directory Router(前回記事) | Agentic RAG |
| Adaptive Knowledge Depth(前回記事) | Adaptive-RAG(Jeong et al., 2024) |
つまりKRFのアプローチは以下のように整理できます。
RAG = Retrieval First(質問が来てから検索する)
KRF = Compilation First(事前に知識をコンパイルしておく)
この「Retrieval First vs Compilation First」という対比が、本記事の技術的な位置づけです。
Knowledge Compilerは、非構造化文書から構造化されたKnowledge Unitを抽出するパイプラインです。
Document → Stage1: Parse → Stage2: Extract → Stage3: Dedup → Stage4: Temporal → KRF Package
今回の入力:製造業の不具合報告書
実験では、製造業の不具合報告書(不良対策書)30件をサンプルデータとして使用しました。報告書のフォーマットは、i-Reporter・MENTENA・現場改善ラボ等で公開されているテンプレートを参考に、以下の項目で構成しています。
| 項目 | 内容 |
|---|---|
| report_id | 報告書番号 |
| title | 件名 |
| occurrence_date | 発生日 |
| product / model | 製品名・型番 |
| lot | ロット番号 |
| location | 発生場所 |
| description | 不具合内容 |
| cause | 原因 |
| action | 対策 |
| prevention | 再発防止策 |
対象製品は6種類です。
| 製品 | 型番 | 件数 |
|---|---|---|
| ProductA | PA-RS485-200(RS485通信モジュール) | 7 |
| ProductB | PB-TEMP-100(温度センサー) | 4 |
| ProductC | PC-MOT-500(モーター制御基板) | 4 |
| ProductD | PD-PSU-24V(電源ユニット) | 5 |
| ProductE | PE-GW-1000(IoTゲートウェイ) | 5 |
| ProductF | PF-PRES-300(圧力センサー) | 5 |
Stage 2: Fact Extraction
各報告書から以下のリレーションでKnowledge Unitを抽出します。
# 報告書の構造化フィールドから直接抽出
(ProductA, has_model, PA-RS485-200)
(ProductA, symptom, "RS485通信モジュールにおいて...")
(ProductA, cause, "電源回路のデカップリングコンデンサ...")
(ProductA, action_taken, "C12を低ESR品に交換...")
(ProductA, prevention, "入荷検査にESR測定を追加...")
# 正規表現による数値情報の自動抽出
(ProductA, baud_rate, "19200bps")
(ProductA, voltage_spec, "50mV")
(ProductA, defect_rate, "5.2%")
(ProductA, related_part, "C12")
Stage 3: Deduplication
同一の(entity, relation, value)トリプルが複数の報告書から抽出された場合、重複を統合し、confidenceを加算します。
10件 → 94 raw units → 84 after dedup(10件除去)
20件 → 175 raw units → 153 after dedup(22件除去)
30件 → 255 raw units → 223 after dedup(32件除去)
データが増えるほど重複排除の効果が大きくなります。
Stage 4: Temporal Integration
同一entityの同一relationで時系列の変化を検出し、valid_toを自動設定します。
ProductA | baud_rate:
2024-01-12: 19200bps (valid_to: 2024-09-02) ← DR-001で記録
2024-09-02: 9600bps (valid_to: null) ← DR-009で記録
これにより「ProductAのbaud rateは最初19200bpsだったが、後に9600bpsの旧機種との互換性問題が発生した」という時系列の変遷が自動的に構造化されます。RAGのチャンクではこの情報は失われます。
KRF Runtime API
KRF Runtimeは4つのAPIを提供します。
krf.lookup(entity) — entity指定時O(1)の直接参照
result = krf.lookup("ProductA")
# → 25 units, 10.7μs
ハッシュマップベースの直接アクセス。entityをキーにして、そのentityに関連する全Knowledge Unitを返します。
krf.history(entity, relation) — 時系列クエリ
result = krf.history("ProductA", "baud_rate")
# → baud_rate:
# 2024-01-12: 19200bps (valid_to: 2024-09-02)
# 2024-09-02: 9600bps (valid_to: null)
RAGでは「ProductAのbaud rateの変遷は?」という質問に正確に答えるのは困難です。複数チャンクから時系列を再構成する必要があるためです。KRFでは temporal index への直接アクセスで即座に返します。
krf.related(entity, depth) — グラフ探索
result = krf.related("ProductA", depth=1)
# → 25 related nodes
# --[has_model]--> PA-RS485-200
# --[symptom]--> RS485通信モジュールにおいて...
# --[cause]--> 電源回路のデカップリングコンデンサ...
NetworkXの有向グラフ上でentityから指定深度まで探索し、関連するノードと関係を返します。
krf.query(question) — キーワードクエリ
result = krf.query("RS485 ノイズ 原因")
# → 7 matches, 175.2μs
# [ProductA|symptom] score=0.67
# [ProductA|cause] score=0.67
全Knowledge Unitのテキストに対するキーワードマッチング。後述するベンチマークで、このAPIの限界が明らかになります。
実験:KRF vs RAG ベンチマーク
比較対象
KRFの比較対象として、TF-IDFベースのRAGシミュレーターを実装しました。
| 項目 | KRF | RAG Simulator |
|---|---|---|
| インデックス | ハッシュマップ + NetworkX | TF-IDF ベクトル |
| 検索方式 | キーワードマッチ | コサイン類似度 |
| チャンク方式 | Knowledge Unit(トリプル) | 報告書を3チャンクに分割 |
RAG側は実際のembedding APIを使わず、TF-IDFベースのベクトル検索で代用しています。これにより外部API依存なしで再現可能な比較が可能です。
重要な注意: 現在のRAGでは bge、e5、jina、OpenAI embeddings 等の高精度なembeddingモデルが使われています。本ベンチマークの「KRFがRAGより2.1倍高速」という結果は、TF-IDFベースRAGとの比較に限定されます。実際のembeddingモデルを使った場合、RAG側のHit Rateは向上し、速度特性も変わります。
スケールベンチマーク結果
10件→20件→30件でのスケール傾向を、各クエリ50回繰り返しのbest-ofで計測しました。
Reports KRF Build RAG Build KRF Query RAG Query Speedup KRF Units RAG Chunks KRF Mem RAG Mem Mem Ratio KRF Hit RAG Hit
10 1.71ms 3.95ms 105.0μs 233.5μs 2.2x 84 30 41KB 638KB 15.5x 90% 100%
20 1.39ms 5.48ms 224.7μs 462.3μs 2.1x 153 60 73KB 1329KB 18.2x 87% 93%
30 2.08ms 9.77ms 343.7μs 731.5μs 2.1x 223 90 108KB 2091KB 19.4x 95% 100%
スケーリング係数(10件を基準)
10件: KRF units 1.00x, KRF query 1.00x, RAG query 1.00x, KRF mem 1.00x
20件: KRF units 1.82x, KRF query 2.14x, RAG query 1.98x, KRF mem 1.78x
30件: KRF units 2.65x, KRF query 3.27x, RAG query 3.13x, KRF mem 2.61x
結果の解釈
1. メモリ効率はスケールするほどKRFが有利になる
10件で15.5倍だった差が、30件で19.4倍に拡大しています。これは2つの要因によります。
- KRFのDeduplication(重複排除)がスケールとともに効果を発揮する(10件で10個除去→30件で32個除去)
- RAGはチャンク数×語彙数でインデックスが膨張するが、KRFは構造化された事実のみを保持する
2. クエリ速度比は安定して約2.1倍
データ量に関わらずSpeedupがほぼ一定です。両者ともクエリ時間はO(N)的に増加しているため、比率は変わりません。現在のKRFのquery()はKnowledge Unitを全走査するキーワードマッチのため、真のO(1)ではありません。entity指定のlookup()であればO(1)です。
3. Hit Rateでは一長一短
10件:KRF 90% vs RAG 100%、30件:KRF 95% vs RAG 100%。KRFが取りこぼしたクエリ(Q2「電源ノイズ 対策」)は、entityが"ProductA"であり、"電源ノイズ"はvalueフィールドにのみ存在するケースです。KRFの現在のquery()はentityベースのインデックスを使うため、entity名を含まないクエリには弱いという構造的な制約があります。
考察
KRFが有利な場面
- entity指定のルックアップ — 「ProductAに関する不具合を全て見せて」のような質問。entity指定であればO(1)で即座に全関連情報を返せる
- 時系列クエリ — 「設定値がいつ変更されたか」「過去の経緯」を扱う質問
- メモリ制約のある環境 — エッジデバイスやローカルサーバーでの運用
- 差分更新 — 新しい報告書が追加された場合、その報告書のみをコンパイルして既存のKRFに追加できる
RAGが有利な場面
- 自由文のセマンティック検索 — entity名を含まない曖昧な質問
- 未知のリレーション — 事前に定義されていない関係性の発見
- 大規模コーパス — Wikipedia全体のような非構造化テキストの大量データ
正直に認める限界
- Knowledge Compilerの実装コスト — 本実験では構造化されたサンプルデータを使っていますが、実際の企業文書(PDFやExcel)からのFact Extractionは未解決の難問です。LLMを使ったExtractorが現実的ですが、その精度と速度がKRF全体のボトルネックになります
- query()のHit Rate — entity名を含まないクエリに対する検索能力はRAGに劣ります。value側の全文検索インデックスの追加が必要です
- スケールの検証範囲 — 30件の不具合報告書は「10TBの社内文書」とはスケールが全く異なります。メモリ効率の傾向は示唆的ですが、大規模データでの検証は今後の課題です
実行方法
全コードはGPU不使用で動作します。
# 依存インストール
pip install networkx --break-system-packages
# サンプルデータ確認
python3.12 sample_defect_reports_30.py
# Knowledge Compiler単体テスト
python3.12 knowledge_compiler.py
# KRF Runtime デモ
python3.12 krf_runtime.py
# KRF vs RAG ベンチマーク(10件)
python3.12 benchmark.py
# スケールベンチマーク(10/20/30件)
python3.12 scale_benchmark.py
今後の展望
外部重みアーキテクチャにおけるKRFの位置づけ
前回記事で提案した外部重みアーキテクチャにおいて、KRFは W_external の一実装です。全体像を改めて整理します。
y = f(x, W_static, W_external)
W_external
├─ Directory Router ... フォルダ選択(前回記事で提案)
├─ Hierarchical File Attention ... 段階的絞り込み(前回記事で提案)
├─ Adaptive Knowledge Depth ... 探索深度の動的制御(前回記事で提案)
└─ Knowledge Runtime Format ... 知識のコンパイルと直接アクセス(本記事で実装)
前回記事では「情シスの役割はAIの知識品質を管理する部門になる」と述べました。KRFのKnowledge Compilerは、まさにその「知識品質管理」を自動化するツールとして機能します。非構造化文書をKnowledge Unitに変換する過程で、重複の排除、時系列の整理、信頼度の付与が行われるからです。
Directory Router + KRF の統合
前回記事のDirectory Routerは「質問から関連フォルダを選択する」機能でした。KRFと組み合わせると、より効率的なパイプラインが構成できます。
質問: 「ProductAのRS485通信障害の原因は?」
Step 1: Directory Router
→ /品質保証/障害報告/ (0.91)
→ /設計/回路/ (0.82)
Step 2: KRF Runtime(選択フォルダ内のKRFパッケージのみロード)
→ krf.lookup("ProductA") ... O(1)、10.7μs
→ 25 Knowledge Units 取得
Step 3: LLM
→ 構造化された知識をプロンプトに注入
RAGでは Step 2 がベクトル検索(全チャンク走査)になりますが、KRFではハッシュマップルックアップで完結します。前回記事の Knowledge Activation Map も、KRFのconfidenceフィールドをそのまま使って可視化できます。
Adaptive Knowledge Depth との対応
前回記事で提案した Adaptive Knowledge Depth(質問の複雑さに応じた探索深度制御)は、KRFのグラフ探索深度と直接対応します。
簡単な質問 → krf.lookup("ProductA") ... depth=0, 直接ルックアップ
普通の質問 → krf.related("ProductA", depth=1) ... depth=1, 隣接ノード探索
難しい質問 → krf.related("ProductA", depth=3) ... depth=3, 3ホップ先まで探索
前回記事では「浅い質問は1フォルダ3ファイル、深い分析は8フォルダ30ファイル」と概念的に述べていましたが、KRFのグラフ探索深度パラメータにより、これを定量的に制御できるようになります。
残る研究課題
今回のプロトタイプから、次のステップとして以下が見えています。
- Knowledge Compilerの高度化 — LLM(Gemini Flash等)を使った非構造化PDFからのFact Extraction。サンプルデータではなく実際の企業文書での検証
- value側の全文検索インデックス追加 — Q2ミス(entity名を含まないクエリ)への対処。KRFのentityベースインデックスとRAGのセマンティック検索のハイブリッド
- 大規模データでの検証 — 30件ではなく数千件〜数万件規模でのスケール傾向確認。メモリ効率の優位性(19.4倍)が維持されるかの検証
- 差分更新の実装 — 新規報告書追加時の増分コンパイル。既存のKRFパッケージへのマージ処理
まとめ
- KRFは前回記事で提案した外部重みアーキテクチャ(W_external)の具体的なデータフォーマットとランタイム実装です
- 「AIが検索するのではなく直接アクセスする知識形式」という設計思想に基づき、Knowledge Compiler → KRF Package → Runtime Lookup のパイプラインを実装しました
- 製造業の不具合報告書30件を対象に、RAG(TF-IDFベース)と比較した結果、クエリ速度2.1倍・メモリ効率19.4倍を確認しました
- ただしHit RateではRAGに劣る場面があり、entity名を含まないクエリに対する検索能力が課題です
- 前回記事の Directory Router + Adaptive Knowledge Depth と組み合わせることで、フォルダ選択→KRFルックアップ→LLMという、検索を含まない推論パイプラインが構成可能です
- 知識のコンパイルという発想自体は有望ですが、Knowledge Compiler(非構造化文書からのFact Extraction)の実現が最大の技術的ハードルです
KRFはRAGの代替を目指すものではありません。企業固有知識を事前にコンパイルし、entityベースの知識参照を高速化する実験的な知識ランタイムです。今後、Knowledge Compilerの精度向上と大規模データでの検証が、このアーキテクチャの価値を決定します。
本記事のコードは全て再現可能です。ご自身の環境で計測し、数値が異なる場合はCPU性能差によるものです。
環境情報
- 計測日: 2026-06-27
- OS: Ubuntu 24.04 (WSL2)
- Python: 3.12.3
- CPU: Intel Core i9-9900K
- networkx: 3.6.1
関連記事
- 社内サーバーの10TBをAIの知識にする ― 外部重みアーキテクチャとAdaptive Knowledge Depthの提案 — 本記事の前提となるW_static / W_external の設計思想と、Directory Router・Hierarchical File Attention・Adaptive Knowledge Depth の提案