はじめに
研究室AI基盤に導入するナレッジツールを探していたら、どうも微妙に考えに合うものがなく、思わず自作してしまったので、その紹介をします。とは言っても新しいナレッジベースを開発したとか、新しいRAGの仕組みを開発したとかではなく、プロジェクト単位で階層構造を保持したままRAGに登録するため、ファイルのパス情報などのメタ情報を抽出して登録するindexserを自作したという話です。
今後、プロジェクト横断で検索したり、プロジェクトを限定して局所化するための小さなMCPサーバも追加する予定ですが、できるだけ既存OSSを活用して最小限の自作でとどめるつもりです。
自作したツールは以下で公開しています。
開発の経緯
研究室では、
- 「先生、〇〇先輩の卒論を引き継げって言われて、卒論と実験プログラムをわたされたけど、とこから読めばいいか、どう読めばいいかわかりません」
- 「先生、〇〇先輩が似たようなコードを書いていたって言われましたけど、どこに該当部分があるかわかりません」
- 「先生、このロボットのマニュアルっていってどっさり資料を渡されたけど、いっぱいありすぎてどこをどう読めばいいかわかりません」
という場面がよくあります(実際には、学生はそう思ってるだけで先生には言ってきません。結果として研究が進まなくなり、さらにはそれが怖くて来なくなったりします)。こういうことを研究室AIに相談できれば学生も聞きやすいし、先生に聞くべきポイントも、どの部分をどう聞けばいいかもAIと一緒に整理することができます。目指すのは研究室の生き字引みたいな優しいドクターAIですね。
つまり手持ちのマニュアルや参考文献、参考プログラム、研究室共有のプロジェクト(ドキュメント、コード、データの混合物)資産を参照しながらAIに相談するというのが目的で、いわゆるナレッジベースとかRAGとかいうものです。最近はOpenWebUIやAnythingLLM, DifyなどRAGを構築できるツールも充実しています。しかし実際に使ってみると、「プロジェクト資産をナレッジとして長期運用する」という用途では少し物足りない部分がありました。
そこで作ったのが filesystem-knowledge-bridge です。今回は第一段階として Indexer が完成し、Open WebUIのExternal Knowledge Sourcesから利用できるようになったので紹介します。
私がナレッジに求めるもの
まず「研究室のナレッジとは何か」を整理しました。
第一に想定しているケースとしては、卒業した先輩の引き継ぎ資料一群です、卒論・修論の論文、対外発表の論文、その中の実験結果を再現するためのプログラム、実験条件、実験データ(の参照)などをまとめるように指示すると思いますが、まとめ資料はいい加減であるがままかき集めたくらいがせいぜいかと思います。
第二に想定しているケースは、研究で使う特殊なシステムやライブラリのマニュアル類です。製品としてドキュメントがまとまっているものもあれば、研究用途だと割とあるがままの内部構造の資料がどっさりということも多いと思います。
その他にも、参考文献集、利用しているOSSのソース・マニュアル一群などもあると思います。
つまり、私が欲しかったのは、単にPDFやMarkdownを検索できるRAGではなく、研究・開発で長期間利用できるナレッジであり、次の条件を満たすことを目標にしました。
1. ナレッジの単位は「プロジェクト」である
ナレッジは単一の文書ではなく、フォルダ階層を持ったプロジェクト全体として扱います。フォルダ構造も重要な情報であり、検索後に元の構造へ戻れることを前提とします。
2. プロジェクトには様々な種類の情報が含まれる
プロジェクトには
- README
- 設計書
- ソースコード
- 実験条件
- 設定ファイル
- 学習済みモデルへの参照
- データセットへの参照
- 論文
など、多様な情報が混在しています。
これらを一つの成果物として扱えることを重視しました。
3. 共有ナレッジと個人ナレッジを区別できる
研究室全体で共有する資産と、個人だけが利用する資産は性質が異なります。
そのため、
- Shared Knowledge
- Personal Knowledge
を区別し、検索対象を適切に局所化できることを重要視しました。
4. 原本の特定ファイルを参照できるパス情報を保持する
場合によっては原本に当たることが必要ですが、原本そのものをナレッジDBに登録して毎回AIが参照するのは重すぎます。検索用のチャンクに原本のパス情報を含むメタデータを登録し、原本はNASやファイルサーバ上に保管して必要に応じて参照します。
5. 個人ナレッジは利用者自身が登録できる
個人ナレッジは管理者が一括登録するものではなく、利用者自身が必要に応じて登録・更新できることを目標としています。
6. 対象は「フリーズしたプロジェクト」
対象プロジェクトは開発中のコード・執筆中の文書ではなく、論文投稿版やリリース版など、ある時点で確定したフリーズ済みプロジェクトを長期間検索・再利用することを目的としています。
既存ツールの調査・比較
上記の条件で、既存のツールを調査してみました。「どのツールが優れているか」ではなく、今回の目的に合うかどうかです。
まず最初の壁が「プロジェクトのフォルダ階層を維持したままナレッジに登録する」という点で、ナレッジに登録するファイルをフラットに扱うものがほとんどでした。フォルダを登録する機能があってもフラット化されてしまったりします。
これは、勝手な想像ですが、フォルダ階層を人間が意識しなくても、検索とAIの読解・分析力でどうにかするという思想によるものじゃないかと考えています。つまりフォルダを扱えない(機能の欠落)じゃなくて意識しなくていい(利点)と考えてるんじゃないかと。
ただ、人間の方はプロジェクトの単位で階層的に考えるのに慣れてるし、その中にはソースもドキュメントも実験設定も混在してるのが自然だと思ったので、あえてプロジェクトのフォルダ階層を維持するという点にこだわりました。
以下で各ツールを紹介しますが、あくまで私が求めるナレッジという観点から見た印象です。
Open WebUI Knowledge
良い点
- Open WebUIだけで完結する
- PDFやMarkdownを簡単に取り込める
- RAG構築が非常に簡単
- Chatとの統合が優れている
目的に合わない点
基本的な単位はドキュメントで、文書検索には非常に便利ですが、プロジェクト全体のフォルダ構造を維持できず、チャンク化された後は、
- どのプロジェクトだったか
- フォルダ構造
- 元ファイルとの関係
はあまり重視されません。Metadataを追加して運用することも考えました。しかし、研究室全体で長期間運用することを考えると、登録ルールを共通化する小さなIndexerがあった方が運用しやすいと判断しました。
ただ、フォルダ階層が重要でない対象には、手軽で便利なのでAd-hocに登録するものはこちらを使うという棲み分けで両立させることを考えています。
Dify
良い点
- AIアプリ開発まで含めた統合環境
- GUIが充実
- ワークフロー構築が容易
目的に合わない点
KnowledgeはAIアプリの部品という位置付けで、組み合わせれば目的を達成できそうでしたが、プロジェクト資産の管理や共有・個人ナレッジなど、かえって工数が増えそうだったのであきらめました。
AnythingLLM
良い点
- セットアップが容易
- 個人利用しやすい
- 多くのEmbedding・LLMへ対応
目的に合わない点
こちらも基本的には文書中心の設計で、プロジェクトをフォルダ階層を残したまま扱うのは難しく、例外的にGitHubの取り込み時にはフォルダ階層が維持されますが、ソースコード意外の論文までGitHubで管理していないので、採用を見送りました。
Qdrant Loader
まだあまり有名ではないようですが、今回一番目的に近いと感じました。
良い点
- フォルダをそのまま取り込める
- Qdrantとの親和性が高い
- シンプルで導入しやすい
最後まで採用候補でした。
目的に合わない点
Qdrant Loaderは、フォルダをQdrantへ登録することは実現できますが、
共有ナレッジと個人ナレッジを区別することや検索結果から元のプロジェクト・フォルダ・ファイルへ戻れることを実現するのが難しそうで採用を見送りました。
Qdrant LoaderでもMetadataを拡張することは可能ですが、この設計を標準の考え方として採用したかったため、登録部分だけを小さく自作することにしました。
filesystem-knowledge-bridgeの位置付け
filesystem-knowledge-bridgeは、
Open WebUIやQdrantを置き換えるものではありません。
位置付けとしては、
Project Folder
│
▼
filesystem-knowledge-bridge
│
▼
Qdrant
│
▼
Open WebUI
というプロジェクトをQdrantへ橋渡しするIndexerです。
検索やRAGは既存のコンポーネントへ任せ、
「プロジェクトをどう登録するか」だけをプロジェクト指向に最適化しています。
抽出・保持するMetadata
今回一番意識したのは、
フォルダ構造を失わないこと
です。
チャンクごとに
- scope
- owner
- project_id
- project_name
- relative_path
- logical_path
- file_name
- chunk_index
を保存しています。
例えば
sample_project/docs/setup.md
なら
relative_path:
sample_project/docs/setup.md
logical_path:
labknowledge://shared/examples/sample_project/docs/setup.md
まで保持しています。
Open WebUIから利用するために
payload.text
payload.metadata
も保存しています。
実際に使ってみる
詳しいセットアップはREADMEにまとめています。
最低限の流れだけ紹介します。
Dockerを起動
docker compose up -d
プロジェクトを登録
kb-index --shared examples
これだけで
shared_examples
というCollectionが作成されます。
Open WebUI
External Knowledge Sourcesで
Provider
Qdrant
Collection
shared_examples
Content Field
payload.text
Metadata Field
payload.metadata
を設定します。
すると
Pythonの必要バージョンは?
のような質問に対して、
登録したプロジェクトから回答できるようになります。
今後
今回自作したのはIndexerですが、これは「AI基盤を自作する」のではなく、「既存のOSSを研究室の運用に合わせて組み合わせる」という考え方の一部です。
今後は
- MCP Server
- Agent向け検索
- 一般ユーザー向けKnowledge登録
- Open WebUI Toolからの登録
- 差分更新
などを追加していく予定です。
ただし、全部自作するわけではなく、Open WebUI・LiteLLM・Qdrantなど、既存の優れたコンポーネントを最大限利用し、足りない部分だけを小さく実装していく予定です。
おわりに
自分にとって一番身近な研究室での利用を例に考えましたが、リリース後のフリーズしたプロジェクトを、プロジェクト単位でフォルダ構造をのこしたままナレッジに登録したい、という要望は他でも通用すると思うので、同じような考えの人の参考になればと思います。
また、こういうツールだと自作しなくても目的を達成できるよ、とか、こここうすればもっと良くなるよ、とかあればぜひコメントをいただければと思います。
次回は、小さいMCPサーバを追加して、プロジェクト横断の検索や参照プロジェクトの限定をする方法について紹介したいと思います。
GitHub