AKARI Tech Blog

燈株式会社のエンジニア・開発メンバーによる技術ブログです

ローカルLLMをiPhoneで動かそう

今週もTech Blogの時間がやってまいりました。本日は DX Solution 事業本部 Dev の許が担当いたします。

さて今年はローカルLLMの性能が話題になることが多いですね。
DeepSeek R1 によるDeepSeekショックに始まり、Gemma 3、QwQ、Phi-4、Llama 4など……。
しかもあのOpenAIが、GPT-2以来6年ぶりにオープンウェイトなモデルを公開するとのこと。


期待していいんだな、アルトマン……!


オープンウェイトなローカルLLMの性能も全体的に上がり、ご家庭のPCでも少し前のGPT-4レベルのLLMが動く時代に。
最近のモデルだと、Gemma 3の27Bモデルがおすすめで、日本語でもかなり自然な対話ができているように感じます。
一昔前のローカルLLMと違い、会話に違和感に覚えることが日に日に少なくなっている、というのが現状です。


PCでローカルLLMがある程度動くようになってきたなら、次に気になるのは普段持ち歩くデバイスで動くかどうか。
そう、スマートフォン上でどれくらい動くかということですね。

ということで、本記事はGemma 3の4B モデルなどの小型モデルを実際にスマートフォン上で動かした記事になります。
スマートフォンで動かせるローカルLLMについて、皆様の解像度が上がれば幸いです。

スマートフォンで動かせるLLMのサイズは?

モデルにもよりますが、おおまかな目安としてパラメーターサイズのBを取った数値の、2倍〜2.5倍程度のメモリがあれば16bitのものが動きます。
量子化するとおおよそ量子化の値に比例して必要メモリが少なくなります。

あるいは、モデルのGGUF自体のファイルサイズ+1GB程度のメモリがあれば最低限動きます。


例えばGemmaやLlamaモデルを読み込むのに必要なメモリの推定値は以下のとおりです。

Gemma 3 モデルの読み込みに必要な GPU または TPU メモリの推定値

ai.google.dev


Llama 3シリーズのモデルの読み込みに必要なGPUメモリの推定値


huggingface.co



実機で動かす場合、バックグラウンドで他のアプリも動作していることが考えられるため、数GB程度の余裕がほしいところです。

最新のiPhone16であれば8GBのメモリがあるため、ファイルサイズが4GB程度のGGUFくらいまでなら動く、というのが目安でしょう。
Gemma 3の4Bモデルであれば、8bit量子化がギリギリ動くか動かないかくらいでしょうか。
(直近3年以内に発売されたiPhoneならメモリ6GBのものが多く、その場合Gemma 3の4Bモデルの4bit量子化がギリギリ動くくらいになります。)



サクッと動かしたいならスマホアプリで

ではどうやって動かしていくかというと、オープンソーススマホアプリが公開されているのでこちらを使うのがおすすめです。*1
2025/4 現在でのおすすめは PocketPal AI と LLMFarm。
どちらもMITライセンスでリポジトリが公開されており、コードの中身まで確認できるため、ユーザーとしては安心、開発者としてはカスタマイズ*2できていいですね。

github.com

github.com

アプリとしてはPocketPal AI のほうが更新頻度が高いため、最新のモデルを動かしたいだけならこちらがおすすめです。



内部的にはどちらもllama.cppを推論用ライブラリとして使用しています。

llama.cppは初代LLaMAが公開された直後の2023/3からある古参の推論用ライブラリで、かつ今でも更新が活発なライブラリ。
Gemma 3が発表された3/12も、その日のうちにGemma 3のテキスト生成に対応させるPRが出ています。

github.com


動かした結果

それでは実際にPocketPal AIを使い、ローカルLLMを動かしてみましょう。
今回動かすのはGemma 3 の4Bを量子化したモデルです。
GGUFへの変換はllama.cppを使って自分で変換してもいいですが、unslothなどがGGUFに変換したものがあるので、こちらをurl指定してダウンロードしましょう。

huggingface.co

Add from Hugging faceで追加可能。Local にダウンロードして使用することも可能。
使用メモリ容量が大きすぎるものは警告が出る

DLが完了したら、使用したいモデルを選ぶだけです。




それではAIに対する代表的な質問をぶつけてみましょう。


Q. 「3.9 と3.11 はどちらが大きい?」


Q. 「レースで3位の人を抜かしました。今何位?」


Q. 「2キロの羽と1キロのレンガはどちらが重い?」


代表的なひっかけ問題も、惑わされることなく回答できていますね。


数学の問題はどうでしょうか。

Q. 「次の数列の規則性を見つけ、次の数を答えよ:2, 6, 12, 20, 30, ?」

階差数列の問題も解けています。



コーディングはどうでしょう。

Q. 「10番目のフィボナッチ数列を求めるためのpython コードを書いて」

def fibonacci(n):
  """
  n番目のフィボナッチ数列を計算する関数
  Args:
    n: 求めるフィボナッチ数列の項数 (n >= 0)
  Returns:
    n番目のフィボナッチ数列の値を返す
  """
  if n <= 1:
    return n
  else:
    a, b = 0, 1
    for _ in range(2, n + 1):
      a, b = b, a + b
    return b
# 10番目のフィボナッチ数列を計算
result = fibonacci(10)
print(f"10番目のフィボナッチ数列は: {result}")

*コードの説明:

*`fibonacci(n)` 関数:
`n` を引数として受け取ります。これは、求めるフィボナッチ数列の項数を表します。
`n` が 0 または 1 の場合、`n` 自体を返します (0番目、1番目のフィボナッチ数列はそれぞれ0、1です)。
それ以外の場合、`a` と `b` をそれぞれ 0 と 1 で初期化します。これらは、フィボナッチ数列の最初の2つの値を表します。
`for` ループを使用して、2番目から `n` 番目までの項を計算します。
ループ内で、`a` と `b` を更新します。`a` は前の `b` になり、`b` は前の `a` と `b` の合計になります。
ループが完了したら、`b` の値を返します。これは、`n` 番目のフィボナッチ数列の値です。
*`result = fibonacci(10)`:
`fibonacci()` 関数を呼び出し、10番目のフィボナッチ数列を計算します。
結果を `result` 変数に格納します。
*`print(f"10番目のフィボナッチ数列は: {result}")`:
結果を画面に出力します。
*実行結果:

10番目のフィボナッチ数列は: 55

このコードは、フィボナッチ数列を効率的に計算し、10番目の項の値を返します。 再帰的な実装よりも高速です。*****

簡単なコードなら書けそうです。




動作速度のイメージとしては、長い回答の場合は5トークン/秒、短い回答の場合は10トークン/秒程度です。(今回使用したのはiPhone 15 Pro Max、メモリは8GB)

5トークン/秒の速度はこれくらい。GPT-4を思い出す速度。





一方で、日本の地理などの知識問題は苦手なようです。





小型モデルゆえの知識量の制約があるとはいえ、
スマートフォンで動作可能な4Bモデルが、自然な会話を成立させる性能に達しているという状況に技術の進歩を感じますね。

小型LLMといえば繰り返し出力だったのに(画像はLlama 3 Swallow 8B)

まとめ

ローカルLLMの小型モデルがスマートフォンで動く時代になってきました。
さすがにChatGPTなどに搭載されているモデルには及ばない一方、Gemma 3 の27Bモデルといった比較的手軽な環境で動作しつつも高性能なモデルが登場しはじめています。
スマートフォン上で動作するローカルでパーソナルなAIの時代が来る日も近いかもしれません。



We’re Hiring!

燈では、最新技術を追いかけるのが好きなAIエンジニアを募集しています!
興味がある方は、ぜひカジュアル面談でお話しましょう!


akariinc.co.jp

*1:自分で実装する場合、llama.cpp以外にもCoreMLやmlxを使うという手もありますが、実際にスマートフォンで動かせるようになるまでひと手間かかります。

*2:余談ですが、先日燈内部で行われたハッカソンではこちらをカスタマイズして動かしました。