1
0

Delete article

Deleted articles cannot be recovered.

Draft of this article would be also deleted.

Are you sure you want to delete this article?

【個人開発】スキーマ設計不要で自然言語をそのまま保存する「intentdb」を自作しました

1
Posted at

はじめに

「自然言語をそのまま保存して、自然言語でそまま検索できるデータベースが欲しい」
これがintentdbを作り始めたきっかけです。

日常的にメモや対話ログをストックしていると、「あの時の話、どこに書いたっけ」という場面が頻繁に起きます。
そこで、スキーマや型定義を一切気にせずプレーンテキストを放り込み、自然言語でそのまま検索・対話できる、インテント(意図)ネイティブなストレージエンジン intentdb を自作しました!

既存のライブラリの単なるラッパーではなく、ストレージエンジンやインデックスまでゼロからスクラッチで実装しています!

開発の背景とコンセプト

一般的なベクトルデータベース(FaissやPostgreSQL + pgvectorなど)は、既存の重厚なDBエンジンのプラグインであったり、環境構築が面倒だったりすることが多いです。

「もっとカジュアルに、1つのバイナリだけで動く、セマンティック検索対応のストレージが欲しい」という思いから、以下のコンセプトで開発しました。

  1. 完全スキーマレス: データはただのテキスト。タグをオプションで付けられるだけ。
  2. 依存ゼロのシングルバイナリ: 外部DB(SQLiteやRocksDB等)に一切依存しない。
  3. 最新AIエコシステム連携: Model Context Protocol (MCP) にネイティブ対応。
  4. オールインワン: CLI、内蔵Web UI、HTTP API、複数端末での同期機能まで1つのバイナリに凝縮。
# スキーマ不要で何でも放り込む
$ idb put "Tanaka bought Product A in March 2024"
$ idb put "Suzuki contacted support last week about a billing issue"

# 自然言語で検索
$ idb search "customers who had problems recently"

1. [score: 0.941] Suzuki contacted support last week about a billing issue
2. [score: 0.812] Tanaka bought Product A in March 2024

導入方法

Crates.ioに登録してあるので、cargo install で一発インストールできます!

cargo install intentdb

# OpenAI APIキーを設定(Ollamaでの完全ローカル運用も可能)
export OPENAI_API_KEY=sk-...

動作要件: Rust 1.75+

Web UIとプロンプト管理体験

idb serve コマンドを実行するだけで、追加モジュールなしでバイナリ単体からWeb UI(デフォルトで http://127.0.0.1:3000)が立ち上がります。

image.png

Timeline(タイムライン)ビュー

AIエージェントとの対話ログやプロンプトを、CLI経由だけでなくWeb UIのTimelineビューから時系列順に視覚的に確認できます。

「Claudeがどういう文脈でこのデータを呼び出したのか」「どういったプロンプトを投げてその応答を得たのか」をWebからいつでも振り返ることが可能です。

image.png

Search / Ask タブ

ストックされたプロンプトやテキストに対して、Webから即座に セマンティック検索 や、 ソース引用付きのRAG(質問応答) をテストできます。

プロンプトを「格納するだけ」で終わらせず、本当に狙い通りのデータが蓄積されているかをGUI上でリアルタイムに確認できる、非常に実用的な仕組みです。

image.png

MCPサーバー対応 (idb mcp)

Model Context Protocol (MCP) 対応しています。

idb mcp コマンドを叩くだけで、本システム自体がそのままMCPサーバーとして機能します。これにより、Claude CodeやCursor、Clineなどのエージェントに、自作のセマンティックストレージを外部記憶として一瞬で連結できます。

image.png

Claude Desktopへの接続例

mcpServers.json に以下を追記するだけで、Claudeが自律的に intentdb へデータを保存(put)したり、過去のログから情報を検索(search)したりできるようになります。

{
  "mcpServers": {
    "intentdb": {
      "command": "idb",
      "args": ["mcp"]
    }
  }
}

認証情報について
OPENAI_API_KEY などの認証情報は、JSONファイル内にハードコードする必要はありません。シェル(.bashrc.zshrc)で設定した環境変数を idb mcp が自動的に引き継ぎます。

AIエージェント自身に「今の対話ログや技術メモ」を勝手に intentdb にストックさせ、必要に応じて引っ張ってこさせる——そんな自律的な長期記憶メカニズムが手軽に構築できます。

技術的なこだわり

1. 独自バイナリフォーマット (.idb)

データは独自バイナリ形式で永続化されます。

マジックナンバーから始まり、可変長のテキスト・ベクトル・タイムスタンプ・タグの配列を効率的にパッキングしています。

HNSWグラフは .hnsw ファイルとして分離保存され、紛失しても .idb から自動で高速に再構築される設計です。

[MAGIC: 4B "IDB2"] [record count: u32]
[record 1]
  [id length: u16][id bytes]
  [text length: u32][text bytes]
  [vector dims: u32][f32 × N]
  [timestamp: u64]
  [tag count: u16][tag length: u16][tag bytes] × N
[record 2] ...

SQLite・PostgreSQL・RocksDBなど、既存のストレージエンジンへの依存は一切ありません。

2. HNSWのスクラッチ実装

ベクトル検索の肝となる HNSW (Hierarchical Navigable Small World) アルゴリズムを、外部のC++ライブラリ(FaissやHNSWlib)を使わずRustでゼロから実装しました。

グラフ構造のノード管理やレイヤーの遷移、コサイン類似度を用いた探索ロジックなど、Rustのメモリ安全性の恩恵を受けながら効率的に動作するようチューニングしています。

3. アーキテクチャ全体像

┌─────────────────────────────────────────┐
│        CLI / HTTP API / MCP Server      │
├─────────────────────────────────────────┤
│         Natural Language Query Engine   │
│     (query → embedding → HNSW search)   │
├─────────────────────────────────────────┤
│         HNSWインデックス(自作)             │
│    Hierarchical Navigable Small World   │
├─────────────────────────────────────────┤
│      カスタムファイルフォーマット (.idb)     │
└─────────────────────────────────────────┘

4. 自作HNSWのパフォーマンス

Apple M2・1536次元ベクトル(text-embedding-3-small)・M=16, ef=50 でのベンチマーク(目安)です。

レコード数 線形スキャン intentdb (HNSW) 加速倍率
1,000 ~8ms ~0.4ms ~20倍
10,000 ~80ms ~1.2ms ~67倍
100,000 ~820ms ~4.8ms ~170倍

データ量が増えるほどHNSWの恩恵が大きくなり、10万件でも約5msで検索できます。

CLIリファレンス

image.png

# 基本操作
idb put "Alice が金曜日に5万ドルの案件をクローズした"
idb put "Dave がログインバグを報告した" --tag bug --tag urgent
idb search "最近のインシデント"
idb search "バグ" --tag urgent
idb list
idb list --tag bug
idb update <id> "更新後のテキスト"
idb delete <id>

# 高度な検索
idb related <id> --top 5          # 類似レコード
idb dedup --threshold 0.95        # 重複検出
idb dedup --threshold 0.95 --delete

# インポート/エクスポート
idb import data.json    # [{"text": "...", "tags": ["a", "b"]}, ...]
idb import data.csv     # text列, 任意でtags列
idb import notes.txt    # 1行1レコード
idb export --format json -o backup.json

# サーバー / MCP
idb serve --port 3000   # HTTP API + 内蔵Web UI
idb mcp                 # MCPサーバーとして起動

HTTP APIとPythonクライアント

idb serve --port 3000
curl -X POST http://localhost:3000/records \
  -H "Content-Type: application/json" \
  -d '{"text": "Alice が案件をクローズした", "tags": ["sales"]}'

curl "http://localhost:3000/search?q=最近の売上&top=5"
curl "http://localhost:3000/records/<id>/related?top=5"
curl "http://localhost:3000/dedup?threshold=0.95"

Pythonクライアントは外部ライブラリ不要(標準ライブラリのみ)で、python/intentdb.py をプロジェクトにコピーするだけで使えます。

from intentdb import Client

db = Client("http://localhost:3000")
db.put("Alice が金曜日に5万ドルの案件をクローズした", tags=["sales"])

results = db.search("最近の問題", top=3)
for r in results:
    print(f"[{r['score']:.3f}] {r['text']}")

その他の機能

  • ハイブリッド検索 (--alpha): セマンティック検索とキーワード完全一致のブレンド比率を調整可能
  • 複数デバイス間の同期 (idb sync): データロスなしのアディティブ(追加型)仕様で安全に同期
  • 完全ローカル対応(Ollama): 外部APIを一切使わず、ローカルLLM/Embeddingモデルのみでオフライン運用も可能

おわりに

Rustでの独自ストレージエンジン開発、HNSWのスクラッチ実装、そしてMCP・Web UI・同期機能まで含む実用的なエコシステムの構築は、非常にエキサイティングな挑戦でした。

個人のローカルメモ帳から、AIエージェントの外部記憶(MCP)、スキーマレスCRMまで、アイデア次第で幅広く使えるプロダクトになっています!


参考

1
0
0

Register as a new user and use Qiita more conveniently

  1. You get articles that match your needs
  2. You can efficiently read back useful information
  3. You can use dark theme
What you can do with signing up
1
0

Delete article

Deleted articles cannot be recovered.

Draft of this article would be also deleted.

Are you sure you want to delete this article?