オフラインファーストAI:通信なしで動くLLMを作る
量子化モデル・厳選コーパス・検索を組み合わせ、ネット接続なしでもAIアシスタントを動かす設計と、そのコストを解説します。

停電から9時間。携帯回線は混雑して使えず、ガレージの冷凍庫には土曜日に買った肉がぎっしり。これ、まだ食べられるかな? いつもならチャットボットに聞くところですが、今いちばん先に壊れたのはインターネットです。 こうしたシナリオを設計要件にしたのが、オフラインファーストAIツールという新しいクラスのソフトウェアです。アシスタントも参考資料のライブラリも、すべてノートPC上で動きます。モデル、コーパス、検索インデックスがすべてローカルにあるので、LANケーブルを抜いた状態でも「この水の浄化方法は?」と聞けば同じように答えが返ってきます。防災グッズとしてより、アーキテクチャの課題として面白いと感じています。ネットワークを取り払うと、クラウド型AIなら無視できる設計判断を迫られ、その判断は緊急時以外でも十分役立ちます。自前のハードウェアで大規模言語モデルを動かすことを考えたことがあるなら、オフラインアシスタントの制約はその問題の最前線にあたります。
オフラインファーストAIに必要な構成要素
クラウド型のアシスタントは、いわば薄いクライアントです。端末がテキストを送り、データセンターがトークンを返します。オフラインのアシスタントは、その全スタックを一般的なPCの上に再現しなければならず、大きく3つのものを用意して整合性を保つ必要があります。 まず推論エンジンです。実質的にはllama.cppかその派生版になります。Apple Silicon、一般的なx86 CPU、コンシューマ向けGPUのどれでも単一の依存ツリーで動くためです。Mac版アプリはこれを同梱し、Windows版はセットアップ時に取得します。どちらにしても、ユーザーのマシンにあることを前提にはできません。初回起動時に、静かにインストールしておく必要があります。 次にモデルです。ここが面白いところで、後ほど詳しく触れます。ふさわしいモデルの選定こそが、この設計の中心的な問題だからです。 3つ目はライブラリです。ある製品では、Wikipediaの閲覧数上位の約93万記事、MedlinePlusやWikiMedなどの医療リファレンス、FEMAやCDCの緊急時ガイダンス、軍のサバイバルマニュアル、wikiHow、iFixitの修理ガイド、そして住宅修繕やアマチュア無線などのStack Exchange Q&Aダンプが収録されています。すべてプレーンテキストで、ライセンス情報は記事ごとに保持・表示されます。フルダウンロードは約9GBで、インストール後は19GBに膨らみます。WikipediaとiFixitを外した軽量版は1.3GBです。どのソースを残すかを決めた時点で、これはエンジニアリングであると同時にキュレーションの仕事でもあります。 これ全体を、クリック数分の3ステップのセットアップに収める必要があります。ダウンロードには最大2時間半かかります。この最後の数字は見た目以上に重要です。ダウンロード期間が、何かを取得できる唯一の機会だからです。これは再起動も接続もできないソフトウェアに求められる規律と同じですが、接続できない環境が嵐で暗くなった台所というだけの違いです。
モデル階層化の問題:1つのアプリに複数の頭脳
クラウドのソフトウェアが決して直面しない判断がここにあります。ユーザーがどんなハードウェアを使っているかはわからず、RAMを調べてもっと大きなクラスタに振り分けることもできません。しかもその答えは、ダウンロードサイズと、その後のすべての回答の質を永続的に左右します。 この種のツールで採用されている解決策は、ハードウェアを調べて階層化することです。初回起動時に、アプリがシステムメモリを確認し、収まるモデルを選びます。 - 128GB以上:大型のフラッグシップ級モデル(あるビルドではNVIDIA Nemotron 3.5 Superを使用、ディスク上で約80GB)。プロジェクトが実施したブラインド採点のテスト(停電時と応急手当の質問)で22問中21問正解。 - 32〜96GB:約27Bパラメータの中規模モデル(約18GB)。同じく22問中21問正解。 - Windowsの32GB:速度を重視したチューニング版の約25GBモデル。22問中19問正解。 - 16〜31GB:8Bクラスのモデル(約6GB)。22問中14問正解。 最後の行をもう一度読んでみてください。ほとんどの人が実際に持っているマシン、つまり16GBのノートPCには、公式ガイダンスの要点を3回に1回ほど外すブレインが割り当てられます。しかも、その要点が「室温に6時間置かれた鶏肉は食べない」といった内容の質問での話です。 これがオフラインファーストAIの居心地の悪い計算式です。量子化と小型モデルは本当に良くなりました。よくチューニングされた8Bモデルは、優れた文章作成アシスタントであり、まずまずの検索インターフェースでもあります。ただし、品質の曲線はデプロイの制約に合わせて曲がってはくれません。クラウドアプリがより賢いモデルを必要とすれば設定フラグを切り替えるだけです。オフラインアプリがそれを必要とすれば、ユーザーが3年前にもっと大きなノートPCを買っている必要があります。曲線を出荷すれば、今度は曲線があなたを出荷することになります。 正直な緩和策は、これらのツールが採用しているものです。小型モデルをコーパスの権威ではなく、コーパスへのインターフェースとして扱うことです。8Bの階層では時々間違えることを設計者が知っているので、すべての回答で、どの記事を読んだかを正確に示し、該当箇所をハイライトします。
検索は機能ではなく、信頼の土台
今ではRAG(検索拡張生成)システムはどれも情報源を示します。クラウドではチェックボックス一つの機能で、透明性を演出しているにすぎないこともあります。オフラインでは、検索が構造を支える柱になります。もっともらしく聞こえる幻覚と、緊急時にユーザーがそれに基づいて行動してしまうことの間に立つ、唯一のものだからです。 そこで生まれる設計は次のようなものです。モデルがプレーンテキストのライブラリを検索し、上位の該当箇所を読んで、読んだ内容を引用しながら回答を書きます。ユーザーが何かを調べるよう頼めば、すでに記憶から答えていても検索を行い、UIは各回答がどのモードから来たかを示します。記憶から、開いた記事から、あるいは開かなかった検索結果から、のいずれかです。最後の区別は微妙ですが重要です。「一致する断片を見つけた」と「記事を読んだ」は、信頼性の異なる別の主張であり、インターフェースもそのように扱います。 私が気に入っている失敗モードの扱いもあります。モデルが検索に出かけたものの最終回答を書けなかった場合(小型モデルでは実際によく起きます)、アプリは見つけた最良の記事を強制的に与えて、もう一度だけ試させます。ユーザーには何も見せません。オフラインでは、より大きなモデルに切り替えたり、再試行キューに投げたりはできません。再試行を、エージェントのループに組み込むしかないのです。これはLLMエージェントは分散システムのように振る舞うと言われるときの意味を示す、小さいながら良い例です。あらゆる箇所で部分的な障害が起きるので、オーケストレーション層の仕事は、障害を生き延びられるようにすることです。 もう一つ真似する価値のある設計があります。推論の予算です。アプリは、回答前にモデルが考えてよいトークン数を、オフ、1,000、4,000、16,000、無制限から選べるようにしています。上限に達すると思考は打ち切られ、モデルはそれまでの材料で答えます。バッテリー駆動中には、堂々巡りで考えるモデルは単に間違っているだけでなく、電力を浪費します。厳しい上限を設けることで、際限のない計算問題を有限の問題に変えられます。コンセントが仮想的な存在であるときには、まさにそうした発想が必要です。

懐疑派の指摘は半分正しい(外れている半分について)
このジャンル全体に対する最も鋭い批判はこうです。「LLMを使わずに、検索可能なアーカイブを出荷すればいいのでは?」。Kiwixは何年も前からまさにそれを実践しています。Wikipediaと医療リファレンスを圧縮・索引化し、オフラインで検索でき、ハルシネーションのリスクもなく、ごく非力なマシンでも動きます。キュレーションされたテキストのデータセットであれば、検索エンジンのほうが信頼できるツールだと言えるかもしれません。あるテスターがオフラインアシスタントに「ボウドリルの作り方」を尋ねたところ、部品は合っていたものの動きが間違っていました。モデルは弓をまったく無視して、スピンドルを両手で転がす方法を説明し、さらに摩擦発火では生じない「火花を扇ぐ」ことに言及したのです。検索エンジンは何も生成しないので、この種の間違いは起こしません。 ただ、この批判はこうしたシステムでLLMが実際に果たす役割を見落としていると思います。設計を最も強く擁護するなら、役割を言い直すことです。モデルは「オラクル」ではなく「検索の知性」として使う。キーワード検索は、語彙がわからないときに失敗します。部品名ではなく、壊れた状態や症状しか手元にないときです。意味的な検索は「意味が近い」ものには役立ちますが、「仕組みや因果でつながっている」ものは見つけられません。生成モデルは、まさにそのギャップを埋めます。「葉の縁が黄色くなる作物」という入力から、キーワードでは決して見つからなかった5つの調べ方の道筋を示せるのです。モデルの仕事は、適切なページへ導くことです。ページの仕事は、正しいことを書いていることです。 もう一つの批判、「終末の時に備えてLLMが必要なら、スキルを身につければいい」は、人生の助言としては妥当ですが、ソフトウェアへの批判としては役に立ちません。小児の火傷、水の浄化の化学、発電機の修理まで、誰もが応急手当の知識でカバーできるわけではありません。書籍はそのすべてを扱っていて、議論の対象になっているのはインターフェースだけです。 懐疑派が確実に的を射ているのは、22問中14問の階層です。インターフェースの層が3回に1回間違い、すべての回答に「情報源を確認してください」という注意書きが付くなら、やがて誠実な製品は、検索ボックスの付いたアーカイブになるでしょう。LLMが存在価値を持つのは、非専門家をCtrl+Fよりも速く適切な箇所へ導くと実証できる場合に限られます。それはユーザーに関する経験的な問いであって、雰囲気で決めるものではありません。
最小構成のオフラインファーストAIスタック
これを自分で作ってみたいなら、ぜひ試してください。いい週末のプロジェクトになります。骨格は思ったより小さなものです。面白いのは、コードよりも選択のほうです。検索優先のローカルアシスタントをPythonで書くと、おおよそ次のようになります。
import subprocess
from pathlib import Path
CORPUS_DIR = Path("./library") # plain-text articles, one file each
MODEL = "./models/granite-8b-q4.gguf" # quantized to fit 16 GB RAM
def search_corpus(query: str, k: int = 5) -> list[dict]:
"""Dumb but honest: rank articles by keyword overlap.
Swap in BM25 or embeddings later; the interface is the point."""
terms = set(query.lower().split())
hits = []
for f in CORPUS_DIR.rglob("*.txt"):
text = f.read_text(errors="ignore")
score = sum(text.lower().count(t) for t in terms)
if score:
hits.append({"path": f.name, "score": score, "text": text[:3000]})
return sorted(hits, key=lambda h: -h["score"])[:k]
def answer(question: str) -> str:
sources = search_corpus(question)
context = "\n\n".join(
f"[SOURCE {i}: {s['path']}]\n{s['text']}"
for i, s in enumerate(sources, 1)
)
prompt = (
"Answer ONLY from the sources below. Cite them as [SOURCE n]. "
"If they don't cover it, say so.\n\n"
f"{context}\n\nQuestion: {question}\nAnswer:"
)
out = subprocess.run(
["llama-cli", "-m", MODEL, "-p", prompt,
"-n", "512", "--ctx-size", "8192"],
capture_output=True, text=True,
)
citations = "\n".join(f"[{i}] {s['path']}" for i, s in enumerate(sources, 1))
return out.stdout + "\n\n--- Sources ---\n" + citations
print(answer("how long is food safe in a fridge without power"))
この40行ほどのコードに組み込まれた制約こそが、おもちゃではなく製品らしく感じさせる要因です。プロンプトは情報源の外での回答を禁じ、引用は機械的に付加されます(モデルに整形を任せることはしません。実際に、モデルが自分の検索コマンドを列挙した「Sources:」行を捏造するバグがありました)。さらに生成長にも上限を設けています。本番環境に必要だが、ここには含まれていないものもあります。意味検索のための埋め込みインデックス、推論トークンの予算、モデルファイルを選ぶためのメモリ確認、そしてUIに表示するためのファイルごとのライセンス情報です。 ここにないものにも注目してください。ネットワーク通信も、APIキーも、テレメトリもありません。モデルファイルとコーパスがディスク上にそろえば、このプログラムは物理的に質問を外部へ漏らすことができません。プライバシーはポリシーではなく、依存関係の結果として成立するのです。
家に持ち帰ってからもついてくる制約
オフラインファーストで作ると、いくつかの見落としにくい制約が、アーキテクチャに恒久的に住み着きます。 **ストレージとインストールの機会は一度きりです。** ライブラリ全体は、インストール中に約27GBの空き容量が必要で、落ち着いたあとは19GBになります。そして、すべてを初回ダウンロード中に届けなければなりません。台風の最中に、不足した医療リファレンスを遅延読み込みすることはできません。このため、厳しいキュレーションが求められます。93万記事は多く聞こえますが、Wikipediaには何百万も記事があることを思い出してください。誰かが閲覧数で順位を付けて、ロングテールを切り捨てたのです。 **電力は第一級のリソースです。** MacBook Proで計測すると、回答時には約100Wを、質問ごとに5〜40秒消費します。フルバッテリーで約100〜300回の回答が可能です。すると、長い思考の連鎖は単に遅いだけでなく、燃料の判断になります。推論の予算や小型モデルの階層は、最適化ではなく製品そのものになります。 **アップデートの経路が命綱です。** アプリはモデル、ライブラリ、バイナリを、ローカルの状態を壊すことなくワンクリックで更新できなければなりません。次にユーザーが回線を使える機会は、何か月も先かもしれないからです。また、バックグラウンドでのリソース管理も新しい意味を持ちます。あるリリースの修正で、Cmd+Qが推論エンジンを本当に停止するようになりました。以前は、ウィンドウを閉じたあとも数GBのモデルがメモリに常駐していたのです。バッテリー駆動中には、それはメモリリークではなく、熱と時間のリークです。 **ユーザーのファイルも信頼境界に入ります。** 発電機のマニュアルや家族の緊急時計画など、ユーザー自身のPDFを取り込めるようにすると、検索パイプラインは敵対的なほど雑多な入力を扱うことになります。スキャンされたPDF、奇妙なエンコーディング、巨大なファイルです。オフラインでは、そのどれも、クラウドのパーサーに任せることはできません。

緊急時を超えて、このパターンが重要な理由
プライバシーは、ポリシーによる約束ではなく、依存関係グラフの帰結になります。ネットワーク通信のないプログラムは、何一つ漏らすことができません。
緊急時という枠組みが見出しを飾りますが、本当に面白いのはアーキテクチャのほうです。同じスタック、つまりローカル推論、キュレーションされたコーパス、引用付きの検索、厳格な計算予算は、法的に建物の外へ出せない患者データを扱うクリニック、エアギャップされた機器の並ぶ工場フロア、クエリログが負債になりかねない国にいるジャーナリスト、データ通信量に応じて料金がかかる衛星インターネットの研究船など、さまざまな場面で求められるものです。議論の中には、まさにこれを実践している人もいました。電波の届かない土地で、手作業で厳選したライブラリとローカルモデルを使い、旅行前に更新して、光回線が使える場合でも日常的なクラウドAIの利用の大半を少しずつ置き換えているというのです。 私が賭けてもいいと思う方向はこれです。量子化された8Bのローカルモデルと最先端のAPIモデルの差は確かにあるものの、「適切な箇所を見つけて忠実に要約する」といった検索に根ざしたタスクでは、ローカルの選択肢で十分なことが多いのです。そして、十分な性能に加え、限界費用ゼロと確実なプライバシーが揃えば、説得力のあるパッケージになります。最先端のモデルは今後も良くなり続けますし、量子化も同様に進みます。小型モデルは、少し遅れて同じスケーリングの波に乗ります。この効率化の曲線に関心があるなら、フラッシュ級のモデルこそ、推論効率の本当の物語がある場所です。 この分野で何かを設計するなら、私のアドバイスはこうです。パターンを真似してください。終末的な美学までは真似しなくていい。キュレーションは容赦なく行うこと。信頼できる200の文書のライブラリは、読んだことのない93万の文書に勝ります。引用は機械的に行い、モデルに生成させないこと。思考には厳しい予算を与えること。そして、モデルが「オラクル」なのか「検索インターフェース」なのかを、明示的に決めることです。精査に耐えるツールは、後者であることを正直に認めているものです。
まとめ
オフラインファーストAIは、終末を生き延びるための技術ではありません。すべての逃げ道、つまりより大きなモデル、クラウドへのフォールバック、常時接続、無制限の電力が封じられたとき、アーキテクチャがどんな姿になるかを見つける試みです。そこに残るのは、キュレーションされたコーパス、手元のハードウェアに合わせたサイズの量子化モデル、信頼を担う検索、そして緩やかに失敗するよう作られたエージェントのループです。これらはオンラインでも良い規律になります。嵐は、その規律を早く身につけさせてくれるだけです。


