Postgres, TypeScript, Remixで構築する:AI向け超高速メモリエンジンの全貌
大山
新田、お前、最近顔色が悪いぞ。夜なべしてまた新しい技術ばっかり追いかけてるんじゃないだろうな?
新田
大山さん!ちょうど良かったです。今、GitHubでsupermemoryai/supermemoryってヤツを見てたんです。これが、AI時代の「記憶」を扱うのに、すっごく重要になりそうだと思って!
大山
ふむ。「スーパーメモリー」か。物騒な名前だ。何がどう「スーパー」なんだ?♂
新田
これ、ただのデータベースじゃないんです。ソフトウェアエンジニアの視点から見ると、主に3つの点で革命的なんですよ!
AIアプリケーションの「記憶」を扱う
従来のデータベースは、決まった構造のデータを保存するのが得意ですが、AIの対話履歴とか、RAG(Retrieval-Augmented Generation)で使う知識ベースとか、AIが活用する文脈を保持するのには、ちょっと使いづらい。
この「スーパーメモリー」は、AIアプリケーションが必要とする、高速でスケーラブルな記憶エンジンとして設計されています。AIに「長期的な記憶」を持たせるための専用APIだと思えば、分かりやすいですね。
技術スタックの親和性(Postgres, TypeScript, Remix)
採用されている技術がPostgres(データベース)、TypeScript(言語)、Remix(フレームワーク)と、モダンで実績のあるものばかり。
特にTypeScriptで書かれているため、型安全性が高く、大規模開発での保守性が向上します。Postgresを使っているので、すでに多くの企業が持っているインフラに簡単に乗せられますし、拡張性も高いです。
高速性・スケーラビリティ
「非常に高速でスケーラブル」と銘打っているだけあって、AIサービスで一番ネックになりがちな、知識の検索・取り出しの遅延を解消することにフォーカスしています。ユーザー体験(UX)を決定づける部分ですから、これはデカいですよ。
大山 なるほどな。従来のデータベースが「証拠保管庫」だとすれば、こいつは「AI専用のインテリジェンス・ファイル」ってわけか。すぐに参照できて、関連付けられた情報も引き出しやすい。
新田
導入も比較的シンプルで、いつもの開発フローに乗せやすいんです。
基本的な要件は、Node.jsとPostgres環境です。
リポジトリのクローン
git clone https://github.com/supermemoryai/supermemory.git
cd supermemory
依存関係のインストール
npm install
環境設定
.envファイルにPostgresの接続情報(DATABASE_URLなど)を設定します。
新田
Postgresを使うので、PrismaのようなORM(Object-Relational Mapper)が使われている可能性が高いです。
マイグレーションの実行
npx prisma migrate dev --name init
これで、スーパーメモリーが必要とするテーブルがPostgresに作成されます。
npm run dev
Remixが使われているので、開発サーバーを起動すれば、Webアプリケーションとしても動かせますし、APIエンドポイントも利用可能になります。
大山
大規模な事件の捜査資料を整理するのに、まずデータベースを作って、それにアクセスするインターフェースを整備する。手順としては、手堅いな。
新田
実際のAIアプリケーションから「記憶」を操作するコードは、こんなイメージになります。(※公式API仕様に合わせた仮のコードとして見てください)
// supermemory clientのインポート(仮)
import { SuperMemoryClient } from 'supermemory-sdk'; // 実際は公開されているSDKを使う
// クライアントの初期化
const client = new SuperMemoryClient({
apiUrl: 'http://localhost:3000/api/memory', // 自分で立てたサーバーのエンドポイントなど
apiKey: process.env.SUPERMEMORY_API_KEY, // 認証キー
});
/**
* ユーザーの会話セッションを記憶として保存する関数
* @param userId ユーザーID
* @param sessionData 会話のテキスト、エンべディング情報など
*/
async function saveConversationMemory(userId: string, sessionData: any) {
try {
const memory = await client.createMemory({
user_id: userId,
type: 'CONVERSATION_HISTORY', // 記憶の種類を定義
content: JSON.stringify(sessionData.messages), // 実際の会話内容
embedding: sessionData.vector, // 検索用のベクトルデータ(あれば)
tags: ['chat', 'session'],
});
console.log(`新しい記憶が保存されました。Memory ID: ${memory.id}`);
} catch (error) {
console.error('記憶の保存中にエラーが発生しました:', error);
}
}
// 実行例
const recentChat = {
messages: [
{ role: 'user', text: '昨日の会議の議事録はどこ?' },
{ role: 'assistant', text: 'プロジェクトXのフォルダにあります。' },
],
vector: [0.1, 0.5, -0.3, ...], // エンべディングは省略
};
saveConversationMemory('user-001', recentChat);
/**
* 関連性の高い記憶を検索し、AIのプロンプトに含めるための情報を取得する関数
* @param query 検索クエリ(例: '議事録')
*/
async function retrieveRelatedMemories(query: string) {
try {
const searchResults = await client.searchMemories({
query: query,
limit: 5, // 上位5件を取得
tags: ['chat', 'document'], // タグで絞り込み
// vectorQuery: [0.2, -0.1, ...], // ベクトル検索も可能
});
console.log(`'${query}'に関連する記憶:`);
searchResults.forEach((memory: any) => {
console.log(`- ID: ${memory.id}, 内容の一部: ${memory.content.substring(0, 50)}...`);
});
// 取得した記憶をAIへのRAGプロンプトに組み込む...
// const promptContext = searchResults.map(m => m.content).join('\n---\n');
// ...
} catch (error) {
console.error('記憶の検索中にエラーが発生しました:', error);
}
}
retrieveRelatedMemories('昨日の会議');
大山 ふむ、これが「AI時代のAPI」ってわけか。従来のSQL文をごちゃごちゃ書かなくても、AIが必要な形式で「保存」と「引き出し」ができる。これは、お前のいう通り、AIアプリ開発のスピードを格段に上げる強力な武器になりそうだ。
新田
はい!大山さん!この「スーパーメモリー」を使いこなして、AIアプリケーションの「長期記憶」という難事件を解決してみせます!