OmniRAG(オムニRAG)は、質問の意図を判定し、データベース照会・ベクトル検索・ナレッジグラフ探索のどれで文脈を集めるかを質問ごとに選ぶRAG(検索拡張生成)の設計パターンです。MicrosoftのAzure Cosmos DBチームが提唱し、GitHubでリファレンス実装「CosmosAIGraph」を公開しています。この記事では、定義と5つの原則、CosmosAIGraphが実際にどう振り分けているか(判定のコード・0件時の切り替え・3ソース同時取得)、同じ名前の論文との違い、採用を避けるべき場面を一次情報で整理します。
まとめ:OmniRAGの要点
- 取得先を意図で切り替えるRAG設計パターン。製品名ではなく、複数の取得先を扱う設計パターンです。CosmosAIGraphではDB照会・ベクトル検索・グラフ探索の3つを使います。
- 実装はCosmosAIGraph(MIT・Microsoftのサポート対象外のリファレンス実装)。Azure Cosmos DB for NoSQLとApache Jenaのグラフで動きます。
- 判定は2段構え。4語未満で照会語から始まり、既知の名前を含む質問はLLMを呼ばずにDBへ回し、それ以外はLLMに「db・vector・graph」の一語で答えさせます。判別できない出力はベクトル検索に倒します。
- DBとグラフが0件ならベクトル検索で補う。利用者が取得先を手で指定したときは補いません。「all」を選ぶと3ソースを並列に引きます。
- 「Omni-RAG」という同名の論文が2本ある(SIGIR 2025 LiveRAGのクエリ分解手法、医療RAGの論文)。どちらもMicrosoftのOmniRAGとは別物です。
- 質問の型が偏っている場面では過剰。類似文書の検索が大半なら通常のRAGかハイブリッド検索で足ります。
OmniRAGの定義と提唱元
RAGは、外部のデータから文脈を取り出してLLMに渡し、回答を生成させる構成です。基本の組み方はLangChainでRAGを構築する手順で扱っています。多くのRAGは取得をベクトル検索1本で行いますが、OmniRAGは「どこから取るか」を質問ごとに変えます。
Microsoft Learnの定義とCosmosAIGraphの位置づけ
Microsoft LearnのCosmosAIGraphのページ(2026-10-30閲覧)は、OmniRAGを、データベースクエリ・ベクトルマッチング・ナレッジグラフ探索から最も合う方法を動的に選ぶ取得の手法と説明しています。選ぶ鍵はユーザーの意図で、意図は簡単な発話解析かAIで質問から判定します。
提唱の場として分かりやすいのは、2025年4月のAzure Cosmos DB Conf 2025です。MicrosoftのAleksey Savateyev氏が「OmniRAG – the right way to do Retrieval Augmented Generation with Azure Cosmos DB」と題して講演し、告知文はCosmosAIGraphをOmniRAGの最初の実装と紹介しています。実装はGitHubのAzureCosmosDB/CosmosAIGraphで公開されており、Azure上のグラフ関連サービスの中での位置づけはAzureのグラフDB比較とCosmos AI Graphの正体で比べています。
READMEが挙げる5つの原則
CosmosAIGraphのREADMEは、OmniRAGの原則を次の5つにまとめています。取得先の振り分けに加え、質問と意図の正解データを整備し続けるSession analyticsも原則に含めています。
- Omni-source with data virtualization:ベクトルストアに限らず価値のあるデータソースを全部使い、データは元の場所・元の形式のまま使って移動や変換を減らす。
- Knowledge graph:既存データからエンティティと関係を取り出し、AIが推論に使えるようにしておく。
- User intent detection:質問を適切なソースへ自動で振り分ける。
- Runtime NL2Query conversion:質問を、ソースごとのクエリ言語へ実行時に変換する。
- Session analytics:質問と意図の正解データ(ゴールデンデータセット)を育て、データの種類や量が増えても意図判定が劣化しないようにする。
同名の「Omni-RAG」論文2本との違い
「omni rag」で検索すると、名前の近い論文が上位に出ます。中身はMicrosoftのOmniRAGと関係がありません。
- Leveraging LLM-Assisted Query Understanding for Live Retrieval-Augmented Generation(arXiv 2506.21384、2025年6月):SIGIR 2025 LiveRAGワークショップで口頭発表されたOmni-RAG。ノイズの多い質問をLLMで書き換え・分解し、サブクエリごとに検索して再ランキングしてから生成します。取得先はWeb文書の検索1系統で、DB・グラフの振り分けは扱いません。
- Towards Omni-RAG: Comprehensive Retrieval-Augmented Generation for Large Language Models in Medical Applications(arXiv 2501.02460):医療の複数知識源に対し、知識源ごとに合うクエリを作る「source planning」を学習させる研究で、知識源の集まりをMedOmniKBと名付けています。
Azure Cosmos DBやCosmosAIGraphの文脈で出てくるOmniRAGは、この記事で扱う設計パターンの方です。資料を読むときは、提唱元がMicrosoftかどうかで見分けられます。
OmniRAGが振り分ける3つの取得先
CosmosAIGraphの振り分け先は、DB照会・ベクトル検索・グラフ探索の3つです。Learnのページには、同じPythonライブラリ(Flask)についての質問でも、意図によって取得先が変わる例が載っています。
| 質問の例(Learnの例を和訳) | 取得先 | 理由 |
|---|---|---|
| Python Flaskライブラリとは何か | DB RAG | 1件の事実を引く |
| その依存関係は何か | Graph RAG | 関係をたどる |
| 作者は誰か | DB RAG | 属性を引く |
| その作者が書いたほかのライブラリは | Graph RAG | 人とライブラリの関係 |
| 全ライブラリと依存関係をグラフで表示 | Graph RAG | 関係の一覧 |
ベクトル検索は、似た文書を探す質問や答えの形が決まっていない質問の受け皿です。Learnは、人物間の間接的なつながり・組織の階層・サプライチェーンの工程を、ベクトル検索では答えにくくグラフなら答えられる質問の例に挙げています。類似度は近さを測れても、関係の向きや順序を持たないためです。ベクトル検索が何を測っているかはベクトル検索とセマンティック検索の違いで説明しています。
CosmosAIGraphでの意図判定の実装
Learnの説明は概念にとどまるので、ここからは2026-07-22時点のmainブランチ(コミット7bce339)のソースで、実際の判定を確かめます。判定はimpl/web_app/src/services/strategy_builder.pyのStrategyBuilderクラスが担います。
LLMを呼ばずにDBへ回す規則(発話解析)
最初に、LLMを使わない規則で判定します。質問が4語未満で、先頭の語がlookup・find・fetch・search・get・retrieve・showのどれかで、残りの語に既知のエンティティ名が含まれていれば、その場でDBに決めます。テストデータでは「lookup Flask」「fetch python pydantic」がこの経路でDBに振られます。コード中のコメントは、この規則を「LLM呼び出しが不要な、速くて安い最適化」と説明しています。Learnの言う「簡単な発話解析」は、実装ではこの程度の規則です。
LLMに一語で分類させる判定
規則に当たらない質問は、LLMに分類させます。システムプロンプトは「取得先はdatabase・vector index・graphの3つだけ」「調べる・探す・取ってくる質問はデータベース」「類似や近さ、答えの決まっていない質問はベクトル」「エンティティ間の関係はグラフ」と指示し、db・vector・graphの一語で答えさせます。返答がJSONで来ても中の値を拾い、どれにも当たらなければvectorに倒します。テストデータでは「get dependencies of the pypi flask lib」「list authors of the pypi pydantic library」がgraphになります。
既定の生成モデルはgpt-5.4、埋め込みモデルはtext-embedding-3-smallで、環境変数CAIG_AZURE_OPENAI_COMPLETIONS_DEP・CAIG_AZURE_OPENAI_EMBEDDINGS_DEPで変えられます(2026-07-22のコミットで更新)。規則で判定できない質問では、分類のLLM呼び出しが1回加わります。この分のレイテンシと費用を見積もりに含めてください。
0件時のベクトル検索への切り替えと「all」
取得はrag_data_service.pyのget_rag_dataが行います。DBかグラフで1件も取れなかったときは、ベクトル検索をやり直して文脈を埋めます。ただし画面で利用者が取得先を指定したときは、指定を尊重して切り替えません。Learnは「グラフで見つけた各エンティティのレコードをDBから引き、それでも無ければベクトル検索」という連携を例示していますが、現行の実装が自動で行う切り替えは「DB→ベクトル」「グラフ→ベクトル」の1段だけです。
2025年9月のリリースでチャット画面に取得先の自動・手動の選択が入り、手動では「all」も選べます。「all」はDB・ベクトル・グラフの3つをasyncio.gatherで同時に引き、ソースごとに「context from db:」のような見出しを付けて1つの文脈にまとめます。意図判定を信用できない質問には有効ですが、3ソース分の文脈がLLMに渡る分だけ入力トークンが増えます。
NL2Queryで取得先ごとのクエリを作る仕組み
取得先が決まると、質問をその取得先のクエリに変えます。READMEがRuntime NL2Query conversionと呼ぶ部分で、3つの取得先で作り方が違います。
- DB:判定で取り出したエンティティ名で、Cosmos DB for NoSQLに
select * from c where c.name in (...)を投げます。LLMにSQLを書かせる方式ではありません。自由な条件で引きたいなら、Text-to-SQLの仕組みを別に組み込むことになります。 - グラフ:質問とOWLのオントロジーをLLMに渡してSPARQLを生成させ、グラフ用マイクロサービスの
/sparql_queryにPOSTします。グラフはApache Jena(apache-jena-libs 5.5.+)のRDFで、Gremlinではありません。画面にはNL2SPARQLのコンソールがあり、Custom Rules機能で業務固有の規則をSPARQL生成のプロンプトに差し込めます。RDFとOWLの関係はオントロジーとRDF・RDFS・OWLの違い、Jenaのサーバー運用はApache Jena Fusekiの解説で扱っています。 - ベクトル:質問を埋め込みに変え、Cosmos DBの
VectorDistanceで近い文書を最大10件(max_doc_countの既定値)返します。Cosmos DB側にはDiskANNのベクトル索引と、VectorDistanceとFullTextScoreをRRFで合わせるハイブリッド検索の関数もありますが、RAGの取得経路はベクトルのみで呼んでいます。RRFの考え方はハイブリッド検索とは?RAGでBM25とベクトル検索を統合する仕組みを参照してください。
PythonによるOmniRAGルーターの最小実装
次の例は、取得先の判定と0件時の切り替えを、自前のRAGに組み込める独立した関数として示したものです。コードはStrategyBuilderとget_rag_dataの流れを簡略化したもので、外部ライブラリなしで動きます。LLMの分類は関数として差し替える前提にし、例では語で決める仮の分類器を入れています。分類結果のJSON解析と「all」による3ソース同時取得は省略しました。
# OmniRAGの振り分けを最小構成で再現する(CosmosAIGraphのStrategyBuilderを簡略化)
from typing import Callable
LOOKUP_WORDS = {"lookup", "find", "fetch", "search", "get", "retrieve", "show"}
KNOWN_ENTITIES = {"flask", "pydantic", "m26"}
def rule_based(question: str):
words = question.split()
# 4語未満・先頭が照会語・既知の名前を含む → LLMを呼ばずにDBへ
if len(words) < 4 and words and words[0].lower() in LOOKUP_WORDS:
for w in words[1:]:
if w.lower() in KNOWN_ENTITIES:
return {"strategy": "db", "name": w.lower(), "algorithm": "text"}
return None
def normalize(raw: str) -> str:
text = (raw or "").strip().lower()
if text in ("database", "db", "dbms"):
return "db"
if text in ("vector", "graph"):
return text
return "vector" # 判別できない出力はベクトル検索に倒す
def determine(question: str, classify: Callable[[str], str]) -> dict:
hit = rule_based(question)
if hit:
return hit
# LLM経路でも既知の名前を拾い、DBやグラフの検索に渡す
name = next((w.lower() for w in question.split() if w.lower() in KNOWN_ENTITIES), "")
return {"strategy": normalize(classify(question)), "name": name, "algorithm": "llm"}
def retrieve(question: str, classify, sources: dict, override: str = None):
s = determine(question, classify)
strategy = override or s["strategy"]
used = [strategy]
docs = sources[strategy](question, s["name"])
# 自動判定のときだけ、DB・グラフが0件ならベクトル検索で補う
if not docs and strategy in ("db", "graph") and override is None:
used.append("vector")
docs = sources["vector"](question, s["name"])
return used, docs
if __name__ == "__main__":
# LLM分類の代わりに語で決める仮の分類器(本番はLLMに一語で答えさせる)
def fake_llm(q):
if "dependencies" in q or "authors" in q:
return "graph"
return "database" if "about" in q else "Vector"
sources = {
"db": lambda q, n: [{"name": n}] if n else [],
"graph": lambda q, n: [], # グラフが空振りした想定
"vector": lambda q, n: [{"name": "similar-doc"}],
}
for q in ["lookup Flask", "get dependencies of the pypi flask lib",
"tell me about flask", "libraries similar to flask"]:
print(q, "->", retrieve(q, fake_llm, sources))
print("override graph ->", retrieve("get dependencies of flask", fake_llm, sources, "graph"))
Python 3.9で実行した出力です。2行目は、グラフが空振りしてベクトル検索で補った結果です。3行目は規則に当たらずLLM側で「database」と分類された質問で、LLM経路でも名前を拾っているのでDBから取れます。最終行のように取得先を指定したときは、0件でも切り替えません。
lookup Flask -> (['db'], [{'name': 'flask'}])
get dependencies of the pypi flask lib -> (['graph', 'vector'], [{'name': 'similar-doc'}])
tell me about flask -> (['db'], [{'name': 'flask'}])
libraries similar to flask -> (['vector'], [{'name': 'similar-doc'}])
override graph -> (['graph'], [])
本番ではfake_llmをLLM呼び出しに替え、KNOWN_ENTITIESをDBの名前一覧から作ります。取得と推論を何度も回す構成に広げるなら、Agentic RAGの設計パターンのように、ルーターをエージェントの1ツールとして持たせる形になります。
GraphRAG・ハイブリッド検索・エージェンティックRAGとの違い
OmniRAGは取得の手法そのものではなく、手法を選ぶ層の設計です。混同されやすい手法と、担う層を並べます。
| 手法 | 何を決めるか | 取得先 |
|---|---|---|
| ベクトル検索のみのRAG | 決めない(取得先は固定) | ベクトル索引 |
| ハイブリッド検索 | 2つのスコアの合成 | 全文索引+ベクトル索引 |
| GraphRAG(MSR) | グラフと要約の作り方 | LLMで作るグラフ |
| OmniRAG | 質問ごとの取得先 | DB・ベクトル・グラフ |
| エージェンティックRAG | 取得と推論の繰り返し | ツールとして持つもの全部 |
GraphRAGとの関係は、CosmosAIGraphのFAQが明言しています。Microsoft ResearchのGraphRAGとは別のプロジェクトで、違いはOmniRAGパターンでn個のデータソースを扱う点とCosmos DBを使う点だ、という説明です。MSRのGraphRAGはLLMで文書からグラフとコミュニティ要約を作る手法で、Azureでの動かし方はGraphRAGをAzureで動かす方法にまとめました。CosmosAIGraphは既存データからRDFのグラフを作ります。ただしOmniRAGというパターン自体は、RDFや特定のグラフの作り方を必須にしていません。ベクトルDBとグラフDBの役割の違いはベクトルデータベースとグラフデータベースの違い、検索の要否から判断を回す構成はエージェンティックRAGとは?が詳しく扱います。
OmniRAGを採用すべき場面と避けるべき場面
採用に向くのは、同じデータに対して「1件の事実を引く」「関係をたどる」「似たものを探す」の3種類の質問が混ざり、しかもエンティティの関係を既存データからグラフに起こせる場合です。CosmosAIGraphの題材であるPyPIのライブラリ(作者・依存関係・説明文)は典型で、部品表(BOM)、組織と担当、契約と取引先のように、マスターデータに関係が埋まっている業務が当てはまります。
次の条件に当たるなら、OmniRAGは入れない方がよいと判断します。
- 質問の大半が類似文書の検索:振り分ける先がほぼベクトルなら、分類のLLM呼び出しが毎回の上乗せになるだけです。通常のRAGかハイブリッド検索で足ります。
- 関係をグラフに起こせない:CosmosAIGraphのグラフ探索は、オントロジー(OWL)とRDFトリプルの整備が前提です。文書から関係を取り出してグラフを整備していなければ、グラフ探索で必要な文脈は取れません。自動判定でグラフが選ばれて0件になると、ベクトル検索に切り替わるだけです。
- データが頻繁に変わる:FAQによると、読み込み後のグラフ更新は参照実装に含まれておらず、Cosmos DBの変更フィードで差分を流す仕組みを自分で作る必要があります。
- 意図の正解データを育てる体制が無い:5つ目の原則のとおり、判定はデータが増えると劣化しうるため、質問と意図の記録を見直す運用が要ります。誤分類した取得先が0件でも、ベクトル検索への切り替えで回答は生成されることがあります。分類結果・取得件数・切り替えの有無を記録し、正解の意図と照合してください。
CosmosAIGraphの実行構成とサポート範囲
CosmosAIGraphは製品ではありません。FAQは「a reference implementation rather than a product」と書き、SUPPORT.mdもMicrosoftのサポート対象のソフトウェア製品ではないと明記しています。問い合わせ先はGitHubのIssuesで、FAQによれば作成元のCosmos DB Global Black Beltチームが顧客案件の中で支援する形です。ライセンスはMITです。
| 項目 | 2026-07-22時点のmain |
|---|---|
| Webアプリ | Python・FastAPI |
| グラフアプリ | Java 21・Spring Boot 4.0.0-M2 |
| グラフエンジン | Apache Jena 5.5系(SPARQL) |
| グラフの置き場 | in_memory(既定)か fuseki |
| 文書とベクトル | Azure Cosmos DB for NoSQL |
| 既定のモデル | gpt-5.4・text-embedding-3-small |
グラフを外部のFusekiに置くかどうかは環境変数CAIG_GRAPH_BACKENDで切り替えます。インメモリのグラフについて、FAQは2,000万トリプル超で試したと書き、グラフには問い合わせに必要な最小限の属性だけを載せるよう勧めています。可用性の面では、Azure Container Appsでグラフサービスを2インスタンス以上にする設定例が載っています。Springが正式版でないマイルストーン版(4.0.0-M2)である点は、本番に持ち込む前に自社の基準と照らしてください。自社データでの意図設計やグラフ化から相談したい場合は、RAG構築支援で対応しています。
よくある質問
OmniRAGは製品名ですか?
いいえ。OmniRAGは取得先を意図で選ぶRAGの設計パターンの名前で、その実装がCosmosAIGraphです。CosmosAIGraphもMicrosoftのサポート対象製品ではなく、MITライセンスのリファレンス実装です。
OmniRAGとGraphRAGの違いは何ですか?
GraphRAG(Microsoft Research)は、LLMで文書からグラフと要約を作って検索する手法です。OmniRAGは、DB・ベクトル・グラフのどれから取るかを質問ごとに決める層の設計です。CosmosAIGraphのFAQも、MSRのGraphRAGとは別のプロジェクトだと明言しています。
「Omni-RAG」という論文はOmniRAGと同じものですか?
別物です。arXiv 2506.21384のOmni-RAGはSIGIR 2025 LiveRAG向けのクエリ書き換え・分解の手法、arXiv 2501.02460は医療の複数知識源への検索計画の研究です。どちらもMicrosoftのOmniRAGパターンとは関係がありません。
ナレッジグラフを使うRAGとベクトル検索だけのRAGは何が違いますか?
ベクトル検索は意味の近さで文書を選ぶため、依存関係・階層・工程の順序のような関係を問う質問に弱くなります。ナレッジグラフはエンティティと関係を明示して持つので、SPARQLなどで関係をたどって答えられます。OmniRAGは両方を持ち、質問によって使い分けます。
Azure以外でもOmniRAGを組めますか?
パターン自体は特定のデータベースに依存しません。CosmosAIGraphはCosmos DB前提ですが、FAQはデータソースの追加を認めており、その場合はStrategyBuilderの判定とLLMのプロンプトを書き換えるよう案内しています。本文のPythonの例のように、判定と切り替えだけなら手元のDBとベクトル索引で組めます。