ローカル環境で常駐型コンパニオンエージェントを構築して得られた教訓

Reddit r/LocalLLaMA / 2026/3/24

💬 オピニオンDeveloper Stack & InfrastructureIdeas & Deep AnalysisTools & Practical Usage

要点

  • 著者は、M4 Mac mini上でRustを用い、ローカル推論にはOllama、SQLiteを裏付けとするセマンティックメモリ、そして必要時にだけクラウドモデルへ段階的にエスカレーションする「モデル・ラダー」を使って、常駐型のセルフホスト・コンパニオンエージェントを構築するまでの数か月にわたるセットアップを述べています。
  • 最大のパフォーマンス改善はメモリアーキテクチャによるものでした。すなわち、BM25のキーワード検索とベクトル類似検索を組み合わせたハイブリッドなリコールにより、永続メモリがないより大きなモデルを、より小さなローカルモデルが上回ることがあり得ます。
  • 本記事は、「システムプロンプト税」を最小化すること(毎ターン必ず知っておく必要がある情報だけを保持する)と、たまに必要となる知識をメモリに保存することが、コンテキスト効率を大きく高めると強調しています。
  • ローカル埋め込み(Ollama経由のnomic-embed-text)により、メモリ操作が実質的にコストフリーになり、大規模に外部の埋め込みAPIを呼び出し続けるための継続的な費用を回避できます。
  • 実践的なエンジニアリング上の学びとして、ツール反復の余裕(headroom)を増やすこと、そしてSQLのリコールロジックを調整して、意図的に保存したメモリがセッションをまたいでも確実に可視化されるようにすることが挙げられます。

ここ数か月、M4搭載のMac miniで自己ホスト型のエージェントを動かしていて、あまり議論されていないと感じたことをいくつか共有したいと思いました。

セットアップはこうです:Rustランタイム、Ollama上で高速なローカル推論を行うためのqwen2.5:14b、さらに必要に応じてクラウドモデルへ段階的にエスカレーションするモデル階層(モデルラダー)。セッションをまたいだセマンティック・リコールのために、ローカル埋め込み(nomic-embed-text)を用いたSQLiteメモリを用意しています。エージェントはlaunchdで24/7稼働し、トレーディングボットを監視し、メールを確認し、Webサイトをデプロイし、重い実装作業はタスクランナー経由でClaude Codeに委譲します。

以下は「実際に重要だったこと」と「重要だと思っていたこと」の違いです:

メモリ・アーキテクチャはすべて。 プロンプト・エンジニアリングに時間をかけすぎて、メモリには十分に時間を割けませんでした。突破口になったのはハイブリッド・リコールです。BM25のキーワード検索とベクトル類似度を組み合わせ、重み付けして統合しました。メモリ・リコールが優秀な14Bモデルは、毎回会話を最初から始めてしまう70Bモデルよりも良い結果になります。

システムプロンプトのコストは本当に効く。 アイデンティティ用ファイルが最初は約10Kトークンでした。メッセージを送るたびにそのコストを毎回払うことになります。そこで、コンテキストとして抱え込むのではなく必要なときにエージェントが参照できるものは徹底的に削って、約2,800トークンまで落としました。エージェントが「たまに」知る必要があるならメモリへ。「毎メッセージで」必要ならシステムプロンプトへ。それ以外はそこに置くべきではありません。

ローカル埋め込みが経済性を変えた。 nomic-embed-textは会話モデルと同じくOllama上で動きます。メモリの保存もリコールも無料です。以前はOpenAIに埋め込みリクエストを送っていました。1回ごとのコストは小さくても、メモリ操作が数千回に積み上がると無視できなくなりました。

モデルラダーはデフォルトモデルよりも重要。 私のエージェントは会話のデフォルトをローカルのqwenにしています(無料・高速)。ただしタスクに応じてMinimax、Kimi、Haiku、Sonnet、Opusへエスカレートできます。重要な洞察は、「人間がモデルを切り替えられるようにする」ことで、自動検出を頑張らないことです。推論が必要なら/model sonnet、ただ雑談しているだけなら/model qwen。単純ですが、それでちゃんと動きます。

ツール反復の上限には余裕が必要。 当初は1メッセージあたり最大10回のツール呼び出しにしていました。妥当そうに見えます。しかし実際のタスク(メール確認、ファイル読み取り、応答の整形など)だと、3〜5回のツール呼び出しを確実に消費します。複雑なタスクなら15〜20回必要です。今は安全網として「200アクション/時」のレート制限を置きつつ、上限25にしています。

最も難しかったバグはセッション跨ぎのメモリ。 メモリを明示的に保存(ストア用ツール経由)しても、session_idがありませんでした。リコールのクエリは現在のsession_idでフィルタしていました。結果として、エージェントが意図的に覚えさせた事実は、将来のセッションでは見えなくなっていました。SQLクエリを1行直すだけで直ります。OR session_id IS NULLを追加することで、突然エージェントがあなたが伝えたことを本当に覚えるようになります。

常駐(パーマネント)なローカルエージェントを動かしている人、他にもいますか? 人が落とし込んだアーキテクチャが気になります。「エージェントを使い捨てのツールとして扱う」パラダイムはよく調べられていますが、「エージェントを永続的な相棒として扱う」には別の設計制約があり、まだ過小評価されていると思っています。

submitted by /u/Constant-Bonus-7168
[link] [comments]