今日のRAG最適解(Hermes Agent/Obsidian)の裏側
TL;DR
RAG を「ベクトル検索」とだけ考えると、かなり大事なものを取りこぼす。
自分の Obsidian Vault と Google Drive を Hermes Agent から検索できるようにしようとして見えてきたのは、検索には少なくとも次の4つの到達経路がある、ということだった。
| 軸 | 何で引くか | 不可約性の源 | 典型的に拾えるもの |
|---|---|---|---|
| ① 全文検索 | 文字列の一致 | 離散的な記号 | 型番、固有名詞、エラーコード、関数名 |
| ② ベクトル検索 | 意味の近さ | 初見対象への意味的汎化 | 言い換え、類義語、概念的に近い文書 |
| ③ 文脈 | 外生的な関係 | 集団・構造から立ち上がる横の縁 | リンク、タグ、共起、地域、時系列、カテゴリ |
| ④ メモリ | 過去の問いの軌跡 | 個人から立ち上がる縦の履歴 | その人固有の調べ方で結びついた文書 |
この4つは、流行している検索アルゴリズムの名前ではない。情報がどこから到達するか の違いだ。
だから私は、今日の RAG の骨格は「単一のベクトルDB」ではなく、全文検索・ベクトル検索・文脈グラフ・問いのメモリを揃え、その上でエージェントが軸を選ぶ構成 に近いと考えている。
この記事は、派手な新技術の紹介ではない。むしろ逆で、あまりにも当たり前に見える4語を、なぜ今あえて分けて言う必要があるのかを書いておくためのものだ。
この記事の立場
この記事は、2026-06-10 時点での自分の設計メモであり、同時に少し先の見立てでもある。
いま、多くの場面で RAG は「ベクトル検索を足すこと」とほとんど同義に語られている。もちろんベクトル検索は強い。言葉のゆれを越えて文書を引けるようになったことは、情報検索にとって大きな前進だった。
ただ、本番の知識基盤で壊れるのは、そこだけではない。
型番を曖昧に引いてはいけない。意味は近くないが構造的に関係する資料を落としてはいけない。組織や地域や時系列が作る文脈を、単なる意味近傍に潰してはいけない。そして、その人が何をどう問うてきたかという軌跡を、ただの「便利なメモリ機能」として消費してはいけない。
私がここで置きたい杭は、次の一文に尽きる。
検索の設計は、アルゴリズムの選択ではなく、情報の到達経路を分けるところから始めるべきだ。
この杭が1年後にどう見えるかは分からない。4という数え方が再編される可能性はある。だが、離散的な記号、意味空間、外生的な関係、個人の問いの軌跡という4種類の起源は、そう簡単には消えないと思っている。
前提:Hermes Agent / Obsidian / Google Drive をどう見ているか
本稿の出発点は、自分の Obsidian Vault と Google Drive を、AI エージェントから実用的に検索できるようにしたい、というかなり素朴な要求だった。
ここで扱う「4軸検索」は、Hermes Agent の公式機能をそのまま説明するものではない。Hermes Agent / Obsidian / Google Drive を使って自分の RAG 基盤を組むなら、検索層をどう切り分けるべきか、という設計上の整理である。
Hermes Agent については、公式ドキュメントで以下のように説明されている。
- Nous Research による self-improving AI agent
- MCP などを通じて外部ツールやローカル環境に接続できる
- 持続メモリは
MEMORY.md(プロジェクト・規約・学び)とUSER.md(その人のプロフィール)として~/.hermes/memories/に保存され、セッション開始時にシステムプロンプトへ注入される - 過去セッションの検索は別系統で、
~/.hermes/state.dbの SQLite に FTS5 全文検索付きで格納される - Obsidian Vault を読み・検索し・作成し・編集する bundled skill がある(記憶DBそのものではない)
したがって、本稿で言う「メモリ軸」は、Hermes の公式メモリ機能そのものと完全に同一ではない。公式メモリ、過去セッション検索、自分で追加する問いログ・検索ログを接続して考えた、RAG 設計上の抽象である。ここを混ぜると記事が弱くなるので、先に分けておく。
はじめに — 4つのパターンに出会うまで
ローカルに置いた Obsidian Vault と、クラウドの Google Drive。この2つを、AI エージェントから「本当に検索できる」状態にしたい。そう思って手を動かしているうちに、私は情報検索のパターンに順番に出会っていった。
最初は全文検索だった。Google Drive がもともと持っている検索は、この軸に近い。だが「予算」で引いて、本文に「コスト」としか書いていない文書は引けない。壁にぶつかってベクトル検索を足した。意味で引けるようになった。
次に、意味では近くないのに関連する文書を取りこぼすことに気づいた。そこで Obsidian のリンク構造やタグを見始めた。
さらに考えると、文脈は Obsidian のリンクに限らない。ECで言えば「この商品を買った人はこれも買っている」、地域で言えば「あなたの地域ではこれが多い」、時間で言えば「今この話題を追っている人は次にこれを見る」。こうした関係は、文書本文の意味だけからは出てこない。
そして最後に、自分が本当に探していたものは、過去に自分がどう問うてきたかという履歴の中にもある、と気づいた。
結果として、4つの検索パターンが手元に揃った。全文検索・ベクトル検索・文脈・メモリ。
短く書くと、あまりにも当たり前に見える。だがこの4語は、実装の部品名ではなく、情報の起源を分けるための圧縮表現だ。順に出会ったこの4つを、私は最初から設計したわけではない——一つの軸の限界が、次の軸を呼んだ。そして辿り着いた先にあったのは「4つの便利な検索手法」ではなく、どの一つでは原理的に覆えない、4つの異なる情報の起源 だった。以下、その4つが「それぞれ別の理由で」潰せないことを示していく。
① 全文検索 — 離散的な記号を守る軸
全文検索は、文字列の一致で引く。ファイル名検索も、エラーコード検索も、根は同じで「その文字列が含まれているか」を見ている。典型的なデータ構造は 転置インデックス だ。語から、その語を含む文書への対応表を持つ。
この軸が強いのは、意味ではなく記号を扱えることだ。型番、請求書番号、固有名詞、関数名、エラーメッセージ。これらは意味的に近いものを引けばよい対象ではない。一字違えば別物になりうる。ECONNREFUSED を探しているときに、「接続エラーっぽい何か」が返ってきても困る。
ベクトル検索は、意味を連続空間に写すことで強くなる。だが、その同じ操作は、一字一句が効く対象では破壊にもなる。だから全文検索は、ベクトル検索の下位互換ではない。完全一致と意味近傍は、優劣ではなく 直交する要件 だ。上位互換が原理的に存在しない。——つまり全文検索は、好みや惰性で残るのではなく、置換できる上位互換が無いから残る。
正直な留保を一つ。硬いのは要件であって実装ではない。BM25 と dense retrieval がハイブリッド検索(RRF 等)の中に溶けたように、製品の輪郭は変わる。ただし、離散的な記号を正確に引く要件そのものは残る。軸としての全文検索は残る。製品の見え方は変わる。
② ベクトル検索 — 初見の対象へ意味で届く軸
ベクトル検索は、テキストを埋め込みモデルでベクトルに変換し、クエリのベクトルと文書のベクトルの近さで引く。正規化すれば、よく言われるコサイン類似度になる。世間で「RAG」と言うとき、暗にこの軸だけを指していることが多い。
これは全文検索の限界を本当に超えた軸だ。「予算」と書いて検索したときに、「コスト」「費用」「見積もり」と書かれた文書を引ける。言葉が一致しなくても、意味が近ければ届く。
だがこの軸の固有の不可約性は、「意味で引ける」ことではない。初見の対象に対する意味的汎化(コールドスタート汎化) にある。全文検索は文字列を要求する。文脈グラフは既存のエッジを要求する。メモリは過去の問いを要求する。だがベクトル検索だけは、その文書についてリンクも履歴も何もない状態から、いきなり意味で引きにいける。これは他のどれも構造的に持てない役割だ。
一方で、②は4軸で最も実装形態が流動的でもある。長文脈化が進むと(手元の Gemma 4 31B ですら長大な文脈窓を持つ)、「top-k を cosine で引いてプロンプトに詰める」という現在の主流実装は、「最初から文脈に入れる」に静かに食われていく。救いは、コーパスが窓を超える限り——Vault と Drive は常に超える——②は 詰める配管としてではなく、選ぶ機構として 残ることだ。機能としては硬い、現在の実装形態としては最も揺れる。
③ 文脈 — 外生的な関係を辿る軸
ここからが、全文・ベクトルとは別の話になる。文脈とは、本文の文字列や意味だけではなく、対象同士の関係から引く軸である。
ここを「Obsidian のリンク」一例で語ると、足元を取られる。人は関連物をリンクするから、リンクされた文書は大体意味的にも近い。良い埋め込みが③の仕事の大半を既に拾ってしまう——その筋で③は②に畳めるように見える。私も一度そう叩いた。
だが③の本体はもっと広い。Amazon を見ればいい。
- 「この商品を買った人は XX にも」 =共起。本文にもリンクにも書かれていない、誰も明示していない縁だ。
- 「あなたの地域では YYY が売れています」 =地理。商品ベクトルのどこを探しても出てこない外生軸だ。
- 「ZZZ に注目する人は感度が高い」 =引いている主体の属性に張られた縁だ。
三つとも、②の意味空間からも、Obsidian の人手リンクからもはみ出す。決定的なのは、これらが 意味的類似度と直交している 点だ。地理的に近い二商品は意味的に遠くてよい。共起する二商品は機能的に無関係でよい(プリンタとインク、おむつとビール)。
だからグラフ埋め込み(node2vec/GNN)で構造的近接をベクトルに写そうとしても、各次元ごとに別の埋め込みが要る。それは「②の特殊ケース」ではなく「②という機構を、別データに再適用した別軸」が次元の数だけ並ぶことになる。③は潰れるどころか、中で分岐して増える。「文脈」は単一の軸ではなく、外生的な縁の束 だ。軸足は、共起・地理・時間・属性・価格帯・新旧……と何本でも取れる。
外生的、というのは、本文そのものの中から自然に導けるとは限らない、という意味だ。人がリンクした。ユーザー群が共起を作った。地域が偏りを作った。時系列が関係を作った。カテゴリ設計が束ねた。これらは、意味とは別の次元で情報を運ぶ。だから文脈は、単なる「意味検索の補助」ではない。意味とは直交する関係を引くための軸である。
④ メモリ — 個人の問いの軌跡を辿る軸
4つめが、私が一番遅れて気づき、そして一番重要だと思っている軸だ。
検索の主体は人間だ。その人間が「何を、どんな順で、どんな意図で問うてきたか」という 問いそのもの を、結果と組にして蓄積していく。すると、問いと文書のあいだに結びつきが溜まっていく。技術的には二階建てになる。
- 検索のたびに
{問い, 引き当てた文書, 実際に役立った文書}を記録する - 過去の問いを埋め込みベクトルにして、文書とは別の「問いインデックス」に溜める
- 新しい問いが来たら、まず文書ではなく過去の問いと照合する
- 似た過去の問いが見つかれば、それに紐づいていた文書を引き寄せる
ここで重要なのは、この経路で引かれる文書が、今の問いと意味的に近いとは限らないことだ。「過去の似た問いに紐づいていた」というだけで引かれる。だから、文書ベクトルを直接引いたのでは出てこない資料が出てくる。「あのとき、この調べ物をしていたら、なぜかこの一見無関係な資料が役に立った」——その経験が記録され、次に似た問いが来たときに効く。
問いと文書を両方ノードと見れば、これは 問いと文書の二部グラフ になる。使うほどエッジが増え、網が濃くなる。
ここでよくある反論は、「それは過去の問いをベクトル検索しているだけではないか」というものだ。半分は正しい。実装機構としては、ベクトル検索を再利用している。ただし、軸として見ているものは検索演算ではない。検索対象と情報の起源 である。文書を意味で引くのが②だとすれば、過去の問いを引き、その問いに紐づいた文書を辿るのが④だ。同じベクトル演算を使っていても、到達経路が違う。
そしてこの軸だけが、コーパスから導出できない。同じ文書集合を持っていれば、全文インデックスも、ベクトル空間も、文書グラフもかなり似たものになる。だが問いの軌跡だけは、その人が問わない限り生まれない。メモリは、文書の関数ではない。人間の関数である。 これは段階の差ではなく、圏の差だ。
文脈とメモリは何が違うのか
文脈とメモリは、どちらもグラフのように見える。だから「文脈とメモリって、結局同じでは?」と言う人が 必ず出る。だが、起源の主語が違う。そして分ける線は、「好みかどうか」みたいな曖昧語よりずっと深い。
文脈は、N人の横の構造。
メモリは、n=1 の縦の履歴。
「この商品を買った人はこれも買っている」は、集団から立ち上がる。あなた自身について何も知らなくても、あなたをある集団や地域に入れた瞬間に候補を出せる。個人の軌跡が空でも、初日から効く。一方で、「あなたは以前この問いをしたとき、この文書を使っていた」は、あなたの履歴からしか立ち上がらない。他人が何万人使っても、あなたの問いの履歴にはならない。
育つものの主語も逆だ。
- ③ 文脈:集団が使うほど、あるいは構造が設計されるほど濃くなる
- ④ メモリ:その人が問うほど、その人の中で濃くなる
形は似ていても、起源の主語が逆。だから片方をもう片方の特殊ケースにできない。だから統合されない。 ——1年後、誰かが「文脈とメモリは同じだ」と言い出したら、集団基底か、個人基底か の一行で切れる。その時に効くのは、議論に勝つことではない。その断層を 先に指していた という記録だ。
ここを分けると、「メモリ」は単なるパーソナライズ機能ではなく、検索の不可約な一軸として見えてくる。
4軸はなぜ代替不能なのか
ここまでをもう一度整理する。叩く基準は人気でも惰性でもない。被包摂耐性——ある軸が他の軸の特殊ケースとして原理的に書き直せてしまうなら、それは独立軸ではなく実装の都合だ。
| 軸 | データ構造 | 情報の起源 | 代替不能な理由 |
|---|---|---|---|
| ① 全文検索 | 転置インデックス | 離散的な記号 | 一字一句が効く対象を、意味近傍に潰せない |
| ② ベクトル検索 | ベクトル空間 | 意味表現 | リンクも履歴もない初見文書へ、意味で届ける |
| ③ 文脈 | 関係グラフ(多次元) | 外生的な縁(集団・横) | 意味とは別の、共起・地域・リンク・時系列を運ぶ |
| ④ メモリ | 問いと文書の二部グラフ | 個人の問いの履歴(縦) | コーパスから導出できない、その人固有の軌跡を運ぶ |
この4つは、同じ種類の不可約性ではない。①は離散性。②は意味的汎化。③は外生的関係。④は個人の履歴。それぞれ、違う理由で潰せない。
だから4軸を揃えることは、冗長性ではなく 被覆性 の話だ。「4つあれば偶然足りる」ではない。他では原理的に塞げない隙間を、独立した4つの不可約性源が、各々別の理由で塞ぐ。ひとつの方法を強くすれば全部を兼ねられる、というものではない。
ここを見落とすと、RAG は「ベクトルDBを入れたのに、なぜか現場では使いにくい」という状態になる。それはベクトル検索が弱いからではない。ベクトル検索に、担当ではない仕事まで背負わせているからだ。
検索と推論の分離 — 軸を選ぶのは誰か
ここで、もう一つ混ぜてはいけない区別がある。この4軸はすべて検索であって、推論ではない。
全文検索は文字列で引く。ベクトル検索は意味で引く。文脈は関係を辿る。メモリは過去の問いを辿る。どれも、来たクエリに対して候補を返す層だ。決定論的で、推論エンジンを起動しない(④の埋め込みすら、変換であって推論ではない)。どの軸を使うか、複数軸の結果をどう混ぜるか、結果が薄いときにどう引き直すか、引けた文書で足りると判断するか——その 判断だけが、4軸の外側にある推論の仕事 だ。検索が賢いのではない。検索を使い分ける判断が賢い。
ここに2つの推論エンジンが乗る。
- フロンティアモデル(Claude):意図を固め、タスクを分解し、どの軸で引くかを選び、返ってきた結果を統合して成果に仕上げる。賢さが要る上位の判断。
- ローカルモデル(Gemma 4 31B 等):エージェント(Hermes Agent)の内側で、クエリの言い換えと「もう十分引けたか」の止め時判断を回す。ローカル環境を知っている実行役。
この分離には、効く帰結がある。検索そのものが決定論的だから、軸の選択を担うローカルモデルは「非力でも実用に乗る」。 クエリの言い換えと止め時判断さえできれば、引く行為自体の賢さは要らない。MCP という1本の線が、この推論層と4軸の検索基盤を繋ぐ。Hermes が手前に立つとして、その下に置くべきは単一のベクトル検索ではなく、4起源が揃った検索基盤 だ。
——ただし正直に言えば、この「推論が軸を選ぶ」という一文は、検索の一番荷重のかかる関数を箱の外に出している。複数軸が返した候補を、この意図にとっての一つの関連度へ束ねる層——reranking / fusion——が、その箱の中にある。RRF も学習型 reranker も、全部そこに住む。本稿が名指したのは 起源の不可約性(source 側)だ。だが検索の moat は、いま source 側ではなく、この 束ね方(ranking 側) に移りつつある。起源は名指せた。束ね方は、まだ名指せていない——そこが次の戦線だ。
そしてもう一つ布石を打っておく。④(メモリ)は、①②③と並ぶ source であると同時に、それらの束ね方を個人化する層 でもありうる。「この人がこの形の問いをするときは、完全一致が欲しくて意味近傍は要らない」を学習し、どの軸をどう重みづけるかを書き換える——だとすれば④は4本目の並列 fetch ではなく、moat の置き場所そのものに触れている。この「より中心的な④」と、それを誰が所有するのかは、別稿(所有の民主化)で扱う。
確度の地図 — 何が硬く、何が賭けか
この記事の主張を、私自身の手で硬さ別に分ける。これは的中したときも、外したときも、両方で意味がある。賭けの境界を自分で引いた文章だけが、当たれば「先見」として、外れても「誠実」として残る。
硬い(予測ではなく含意)。 4つの起源は不可約で、消えない。なぜなら、それぞれが 記号・集団・個人 という情報の出どころに根を張っており、技術の流行より深いからだ。「全文検索は残る」は予測で、当たっても「まあそうだろうね」で終わる。「完全一致と意味近傍は直交要件だから、片方が他方を置換することは原理的にない——ゆえに残る」は、構造から結論が落ちる 形だ。前者と後者は、同じ的中でも記憶のされ方が違う。
賭け(境界はここ)。 「ちょうど4本という分節」が、このままの形で残るか。これは弱い賭けだ。そしてその脆さは、漠然と全体にあるのではなく、③と④の縫い目に局在していた——両者が同じ「育つ関係グラフ」に見えるから。だが上で縫い直した通り、集団基底/個人基底 でその縫い目は閉じる。だから「4」という数字すら、当初より硬くなった。
硬いのは 軸の存在とその理由。柔らかいのは 「ちょうど4本」という数。そしてその柔らかさの所在まで、私は開示する。
(余談だが、この4分節は、独立に何度も、別々の角度から叩き直しても、同じ4つの起源に戻ってきた。脆いのは「4」という数だけで、起源そのものは戻ってくる。)
——なお、賭けはもう一段ある。「4本の 並列 軸」という幾何そのものが、source × signal × fusion という立体を、平面に潰した像かもしれない、という賭けだ。④を並列 source として描いた本稿の像は、④が 他軸を個人化する層 でもある可能性を畳んでいる。その立体を開く作業は、続編に回す。
実装は溶ける。だが抽象は設計言語として残る
製品の輪郭——「全文検索システム」「ベクトル DB」「グラフ DB」「メモリレイヤー」——は、十中八九溶ける。ハイブリッド検索が既に①②を一つのリトリーバに融かし始めている。窓が伸びれば②の「詰める」配管は消える。一つの基盤が、4起源すべてを内部で扱う形へ寄っていく。
だが——ここが効くところだ。統合された実装ほど、設計者は4起源を意識し分けねばならない。 一つの箱に融かすからこそ、中で離散と連続を、集団と個人を取り違えれば壊れる。製品名が消えるほど、この分節は 設計言語として要る。輪郭が溶けることは、抽象が死ぬことの 逆 だ。
集団は、いつこれに気づくのか
ここからは、構造ほど硬くは読めない。私の観測と予想だ(だからここは賭けの側に置く)。
集団は 概念では気づかない。痛みで気づく。 4軸が今この瞬間も真でも、多数派が見ないのは、見なくても困っていないからだ——"RAG=ベクトル検索" で大半のデモは動く。気づきが来るのは、ベクトル一本の構築が 本番で壊れる経験が臨界量に達した ときだ。型番が引けず事故る。地理を意味に畳もうとして破綻する。引き金は知性ではなく 故障率 で、故障率は本番投入量に比例する。
そして4起源は、別々のタイミングで気づかれる。痛みの可視性が違うからだ。
- ① は最速。もう起きている。 ハイブリッド検索が「上級テク」から「標準」へ格上げされつつあるのが、集団が①の不可約性に痛みで気づいた、最初の相転移だ。
- ② は静かに移行する。 痛みが小さく、議論にならないまま実装が変わる。
- ③ は遅れる。 ③の欠落は "事故" ではなく "機会損失" で、見えない。引けなかった関連を、人は損失と認識しない。
- ④ は逆説的に一番遅い。 需要側は「パーソナライゼーション」として先に言語化する。だがそれが "検索の第四の不可約な軸" だと構造的に理解されるのは、最後だ。
全文検索が足りないと、「あるはずの型番が引けない」という明確な失敗になる。だがメモリが足りないと、ただ「なんとなく毎回こちらの意図を分かってくれない」「前に似たことを調べたのに、またゼロから始まる」という 鈍い不満 として現れる。だから多くの場合、メモリは「便利なパーソナライズ機能」として消費される。
ここに、この記事を いま 書く理由がある。構造の硬さと、集団が気づく速さは、相関しない。むしろ逆相関すらしうる。 集団が一番遅れて気づくのは、構造が一番硬い④だ。①は放っておいても痛みが教える。だが④は、誰かが構造で名指さない限り、集団は製品語の霧の中に何年も留まる。 故障率が、決して垂らさない一滴がある。それが、④を「検索の不可約な一軸」として構造で打つことだ。
そしてこの第4軸こそが、私の等式の核に触れる。
知能 × 文脈 = 人格
Claude や Gemma のようなモデルは、知能の項である。全文・ベクトル・文脈・メモリは、その知能が掛かる文脈の項を支える。なかでもメモリは、その人固有の人格を一番濃く運ぶ。同じ知能でも、掛かる文脈が違えば、違う人格として働く。メモリが育つことは、単に「便利になる」ことではない。文脈の項が痩せないための条件である。
オープンソースへの敬意 — 資本の前に、人格の核を灯したこと
この設計を語るうえで、どうしても記しておきたい敬意がある。
第4軸「メモリ」——個人の軌跡を運ぶ、最も硬く、最も遅れて気づかれる層——を、概念ではなく 動く形 で、しかも オープンソース で世に出したのは、Nous Research の Hermes Agent だった。Hermes Agent は、セッションをまたいで対話を読み、その人の好み・要求・環境・学んだことを抽出し、永続的な記憶へ蒸留していく自己改善ループを持つ。
だが記憶の置き場所が肝心だ。Hermes の組み込みメモリは、Obsidian の中ではなく ~/.hermes/memories/ の MEMORY.md(プロジェクト・規約・学び)と USER.md(その人のプロフィール)——どちらも自分のディスク上の、開いて読めるプレーンな markdown——に置かれる。過去セッションは別途 ~/.hermes/state.db の SQLite(FTS5 全文検索)に積まれる。Obsidian はその記憶DBそのものではなく、Vault を読み・検索し・作成し・編集する bundled skill として接続される。
おもしろいのは、訂正後のこの事実が、4軸の見立てをむしろ補強することだ。MEMORY.md/USER.md は「エージェントが対話から蒸留した、その人固有の事実」——④の個人軸そのものだ。そして state.db の FTS5 は、会話履歴に ①の全文軸 を当てたものに他ならない。Hermes は既に、複数の到達経路を別々の置き場所で体現している。
私が「知能 × 文脈 = 人格」と呼んできた等式の、文脈の項を人格にまで高める核心。その実装が、ここにある。そしてそれは 透明(記憶を更新するロジックすらソースで読める)で、手元で動き、自分のものである(記憶は誰かのサーバーではなく、所有する markdown だ)。
公平に書いておく。フロンティア側にも記憶機能はあるし、部分的な公開実装もある。だが 既定の・主流の体験としては、人格に関わる記憶は閉じた・サーバー側の・収益化された形に置かれている。圧倒的な資本を土台にした陣営がそちらを組み上げていくなかで、その同じ核心を——開かれた・手元で動く・自分が所有する・誰もが動かせる形で——先に灯してみせた。これは資本の大小では測れない種類の達成だと思う。巨大な資本が「いずれ」整えるであろうものを、はるかに小さな資源で「すでに」動かしてみせたこと。その事実に、心からの敬意を表したい。
——そして本稿は、私がこの一年書いてきた一枚の絵の続きでもある。「最強のモデル」という名指しの価値がどこから崩れるか(フロンティアモデル包囲網)を追い、Hermes Agent を読み解いてきた。価値が「最強のモデル」から「文脈の起源」へ移るなら、その文脈の第4軸を、開かれた形で握った者が効いてくる。 同じ断層を、私はずっと見ている。
実装に落とすなら(receipt)
ここから先のコードは、この記事の主役ではない。抽象が実装に落ちる地点を示す receipt だ。重要なのは個々の関数ではなく、文書とは別に「問いのインデックス」と「問い→文書のエッジ」を持つ という一点に尽きる。
まず、4軸を別々に作る。
knowledge-base/
documents/ # Obsidian / Drive から同期した本文
index/
fulltext/ # ① 転置インデックス
vectors/ # ② 文書ベクトル
graph/ # ③ リンク・タグ・共起などの関係
memory/
questions/ # ④ 問いインデックス
question_document_edges # 問い ↔ 文書 の有用エッジ
検索時は、すべてを毎回同じ重みで叩く必要はない。どの軸を起こすかは、推論エンジンが intent から選ぶ。
from typing import Literal
Axis = Literal["fulltext", "vector", "context", "memory"]
def choose_axes(query: str) -> list[Axis]:
"""実際には LLM やルールでよい。ここでは考え方だけ示す。"""
axes: list[Axis] = []
if looks_like_identifier(query): # 型番・エラー・固有名詞 → ①
axes.append("fulltext")
if asks_conceptual_or_fuzzy(query): # 概念・言い換え → ②
axes.append("vector")
if asks_related_or_neighboring(query): # 外生的な縁 → ③
axes.append("context")
if similar_question_may_exist(query): # 過去の問いの縁 → ④
axes.append("memory")
return axes or ["vector", "fulltext"]
メモリ軸は、検索のたびに育てる。
def record_search_feedback(question, retrieved_doc_ids, useful_doc_ids):
qid = upsert_question_embedding(question) # 文書とは別の「問いインデックス」へ
for doc_id in useful_doc_ids: # ← "役立った" の信号が縁の質を決める
add_edge(question_id=qid, document_id=doc_id, relation="was_useful_for")
メモリは初日には効かない。だから、最初から完璧に作ろうとしなくてよい。全文・ベクトル・文脈で立ち上げ、検索ログだけ先に溜める。後から問いインデックスを作ってもいい。最初に必要なのは、完成したメモリではなく、記録を始めることだ。
「最適解」と呼べるか
では問おう——この構成を「今日の RAG 最適解」と呼べるのか。
Hermes Agent / Obsidian が、新しい検索アルゴリズムを発明したわけではない。全文検索も、ベクトル検索も、グラフ探索も、個々は既存技術だ。だが RAG を「本当に検索できる」状態にしようとすると、自然と次の構成に近づく。
- 離散的な記号を守る全文検索
- 初見の対象へ意味で届くベクトル検索
- 意味とは別の外生的関係を辿る文脈グラフ
- 個人の問いの履歴を辿るメモリ
- その上に、どの軸を使うかを選ぶ推論エンジン
最適解があるとすれば、それは単一の手法ではなく、この アーキテクチャの形 だと思う。だから答えは、条件付きの Yes になる。
- 単一アルゴリズムとしては No
- 「他では原理的に塞げない隙間を、独立な4つの不可約性源が各々塞ぐ」構成としては Yes。現時点でこれより強い枠組みを、私は知らない
- ただし、第4軸であるメモリはまだ育て方が確立しきっていない。「役立った」という信号の設計など、未解決が残る。フロンティアが動いているのは、まさにここだ
今日の最適解の 骨格 は見えている。①②③は組めるし、Obsidian を使っているなら③の土台はある。残っているのは2つ——④(個人の軌跡)を 育てきる こと。そして、それが製品機能ではなく 検索の不可約な一軸 だと、集団が 気づく こと。後者は、誰かが構造で書かない限り、来ない。
これはバズを狙う話ではない。後から「そういえば、あの時点でその断層を指していた人がいた」と思い出せるように、バケツに一滴を垂らすための記事である。バケツは、もう置かれている。だから今日、一滴を垂らす。
おわりに
Obsidian と Google Drive を1つのエージェントから検索したい、という出発点から、ずいぶん遠くまで来た。だが振り返ると、4つの軸は行き当たりばったりに増えたのではない。一つの軸の限界が、次の軸を呼んでいた。
全文検索は、記号を守る。
ベクトル検索は、意味で広げる。
文脈は、外生的な関係を辿る。
メモリは、個人の問いの軌跡を育てる。
この4本が揃い、その上で知能が文脈を選んで掛かるとき、RAG はようやく「人格を持った検索」に近づく。今日の最適解は、たぶんその形をしている。そして資本ではなく開かれた手によって、集団が最後に気づくその核がすでに灯されていることに、もう一度、敬意を。
参考リンク
- Hermes Agent — Persistent Memory(公式ドキュメント)
https://hermes-agent.nousresearch.com/docs/user-guide/features/memory - Hermes Agent — Memory Providers(外部メモリプラグイン)
https://hermes-agent.nousresearch.com/docs/user-guide/features/memory-providers - NousResearch/hermes-agent(GitHub・memory.md 一次ソース)
https://github.com/NousResearch/hermes-agent/blob/main/website/docs/user-guide/features/memory.md - Gemma 4 model overview(Google AI for Developers)
https://ai.google.dev/gemma/docs/core - Ollama — gemma4:31b
https://ollama.com/library/gemma4:31b