5.1さらうどん

@giginetの技術ブログ。ゲーム開発、iOS開発、その他いろいろ

macOSのβアップデートに失敗して吹き飛んだ話

まとめ

  • メインマシンをmacOS 15.3 Betaに軽い気持ちで上げたら文鎮化
  • データは全て吹き飛んだが、Time Machineがあって事なきを得た。マジでバックアップとろう
  • Apple Careも入ろう

macOSのβアップデートに失敗して吹き飛んだ話

メインマシンにmacOSのβ版を入れて運用していた。近年のmacOSは安定しているし、特にSequoiaにおいては、正式版リリース後もApple IntelligenceやImage Playground、ChatGPTサポート、Apple Vision Proのワイドディスプレイ化などは最新のマイナーバージョンにのみ提供されているため、βを使いたい理由も多かった。

僕の周りにはmacOS/iOSなどのAppleプラットフォーム開発者が多く、会話の中でわりとメインマシン*1にもβ版を入れている人が多かった。僕もまあ大丈夫やろ、と思って、ここ2〜3年はメインマシンにもβ版のmacOSを入れて使っていた。

5日ほど前にmacOS 15.3 Beta 2が配信された。すでに入っている15.3 β1からβ2への更新なので、特に疑問もなく空き時間にアップデートを選択した。しかし、次の日の朝になってもインジケーターがハングしていた。

どうにもならないので電源を切ってしまったところ、ヤバそうな画面が出て文鎮化。

DFUモードからの復活

Macのファームウェアを復活させる/復元する方法 - Apple サポート (日本)

この状態になると、2台のMacを使って、生きている方からファームウェアの修復パッチを流し込む「復活」を行わないとダメらしい。上記のガイドに従ったが、「復活」が上手く行く気配は無し。終わった 😇 この時点でデータロストを覚悟したが、家庭内で運用しているNASを調べてみたところ、年明け以降にバックアップが走っていることが判明。事なきを得た・・・・・・。

結局、自分ではどうにもならないので渋谷Apple StoreのGenius Barに行った。かなり込み入った状況らしくて、店舗のConfiguratorでも初期化が失敗し、このままだとロジックボード交換になるかもと言われた。入ってて良かったApple Care+*2

結果的に二の矢、三の矢を試し、2時間ほど格闘してもらい、ソフトウェアの対応だけで初期化できた。かなり重い症状を引いたっぽい・・・・・・。

β版を入れていたらサポート対象外になるかと思っていたが、かなり丁寧に対応してもらえて印象がとても良かった。Genius Barに行ったのはおそらく10年ぶりぐらいだけど、特にサービスの質は悪くなっていなかったし、都内でも予約がすぐ取れた。

Appleはオンラインでのやりとりは最悪なことが多いが、対面コミュニケーションはかなりちゃんと体験設計されていて、素直に凄いなと思った。

データの吹き飛ばしから、Apple Storeに端末を預けたり、Time Machineで復旧したりで3日ほどかかった。

Time Machineからの復元だけで12時間ぐらいかかってた

バックアップはマジで取ろう

βのバックアップからちゃんと復元できるかを心配したが、警告は出たが問題なく復元できた。多くのアクティブなデータやプロジェクトはiCloudやGitHubで管理しているため、データが吹き飛んで致命的になることは少なくなったが、検証用のコードなんかはいちいちリポジトリを作っていなかったりするので、維持されたのは助かった。 この機会に古いデータを保全するなど、データを整理するきっかけになった。

2年ほど前にTime Machine用のSSDをいちいち繋ぐのが面倒だなと、NASを導入しておいたのが今になって生きた。転ばぬ先の杖。

MacのTime Machineによるバックアップ!HDD、SSD、NASのおすすめポイント | アイ・オー・データ機器 I-O DATA

このI-O DATAの製品を使っているが、家のネットワークに繋いでおくだけで勝手にバックアップが取れるので、心配な方はすぐに導入した方が良い。

僕は20年以上Macを使っていて、今ではかなり古参だと自負しているが、ここまでの症状に当たるのは記憶になかった。慣れすぎているからこそ、β版をメインマシンに入れるのは危ないという当たり前の意識が欠如していた。言うまでもないことですが、β版はメインマシンに入れないでください

*1:iPhoneにも!

*2:筆者はM3 Max 128GBという80万ぐらいするマシンを使っている

iOSでLlama.cppを使ったローカルLLMアプリの構築2024

時代はローカルLLMということで、ちょっと興味があったので、iOS/iPadOS上でローカルLLMを動かしてみた。

MiniAIChat

習作として、ローカルLLMを使った質問応答型のmacOSアプリを作った。ネイティブで書かれており、Apple Platformなら大体動く(Mac/iPhone/iPad/Apple Vision Pro)

質問応答

まずはオーソドックスな質問応答をさせている。ローカルLLMにしてはけっこうな精度で回答できていそう。

ローカルで動いてます

単に以下のようなプロンプトを与えている。後述の日本語LLMのサンプルを参考にしているが、このような催眠術に効果があるかはわからない。

あなたは誠実で優秀な日本人のアシスタントです。特に指示が無い場合は、次の質問に常に日本語で回答してください。
回答は「回答:」から始めて簡潔に答えてください。

\(text)

JSONの生成

手法については後述するが、特定のスキーマに適合したJSONの生成も試している。構造化データを吐き出すのに使えそう。

M3 Max全部盛りを使った高級JSON

CoreML VS Llama

AppleプラットフォームのML基盤と言えば、CoreMLが真っ先に挙げられる。しかし、CoreML向けのLLM(日本語も)は充実していないし、他の既存モデルをCoreML上で動作させるには、coremltoolやHugging FaceのExportersを用いて、CoreML上で動作可能な形式に変換しなくてはならない。

ローカルLLMをCore MLモデルに変換する - 🤗 Exporters の使い方

この記事を書かれた @shu223 と先日飲んでいたところ、「CoreMLのモデル変換は知識がないとハマって難しい」という話を聞いたので、今回は直接LlamaをiOS上で動かしてみることにした。

Llama.cpp

Llama.cppはC++からLlamaを扱うためのライブラリ群だ。そしてなんとSwift Package版も提供されている。

これについて、さらに素晴らしい応用例の記事が既に存在してる 👏 今回はこれを大変参考にした。

基本的な話は上記の記事がほとんど網羅してくれている。概念を学んだり、試してみるのはこの記事を参考にすれば十分なはずだ。

一方で、この記事が書かれた2023年12月から比べて、細かな事情がいろいろと変わっていたので、この記事ではその差分や、ハマったところを中心に紹介する。

サンプルコードのキャッチアップ

Llama.cppには、SwiftUIで実装したサンプルアプリのコードが同梱されている。基本的にこれを参考にできるが、最低限の機能しか実装されていないため、上述のZennの記事のサンプルアプリも一緒に読み込んだ。

また、Swift実装だけでは不十分だったので、Llama.cppのリポジトリに同梱されている examples/simple-chatcommon-sampler の実装も参考になった。

ドキュメントも他の実用例も不足しているので、C++のコードを読みながらSwiftに翻訳していく。上記の記事が書かれた1年前から、samplerなどLlama.cpp内の多くの実装が変更されていたので、PRなども参照しながら移植した。

LLMを選ぶ

基本的にHugging Faceから、Llama用のモデルを選び、差し替えるだけで動作させることができた。

今回、日本語のモデルとして、ELYZAが提供しているLlama 3のLLMを用いた。このモデルを使うと、日本語であってもそこそこの精度で質問応答をしてくれて、期待以上の返答が得られた。

日本語にこだわる必要がない場合は、Meta公式のLlamaのモデルを使うとよい。InstructionCodeLlamaなどを用途に合わせて利用できそうだった。英語の方が精度も良い。

GBNFによる生成結果への制約

Llama.cppでは、GBNFという文法定義のフォーマットを使って、生成される文字列を制約する機能(Grammar)が提供されている。

root ::= answer
answer ::= "回答:" message

message          ::= string+ ([ \t\n] string+)*
string ::= alnum-char | jp-char
alnum-char ::= [^"\\] | "\\" (["\\/bfnrt] | "u" [0-9a-fA-F] [0-9a-fA-F] [0-9a-fA-F] [0-9a-fA-F]) # escapes
jp-char     ::= hiragana | katakana | punctuation | cjk
hiragana    ::= [ぁ-ゟ]
katakana    ::= [ァ-ヿ]
punctuation ::= [、-〾]
cjk         ::= [一-鿿]

JSON Schemaを使ってGBNFを生成する方法も用意されており、これらを正しく実装すると*1、validなJSONをLLMに吐かせることができた。

オンラインコンバーターも提供されていたので、この辺を差し替えるだけで、先述のJSONの生成のような、わりとそれっぽいモノができた。正規化データができてしまえば、いろいろ応用が利きそうだ。

先述の記事の段階では、Llama.cppのライブラリ部分にGBNFのパーサーがなく、本体のコードを移植しなおすなど、ハックが必要だったようだが、本稿執筆時点では、GBNFのパーサー部分がライブラリとして提供されるようになったようで、記事で触れられているような手法を採らずともGrammarの生成が行えた。

トークン生成のAsyncSequence対応

Llama.cppに同梱されているSwiftのサンプル実装ではactorを用いて、生成状態を監視して無限ループするという実装になっているが、どうにも扱いづらいAPIなので、AsyncSequenceを使ったものに書き換えてみた

let session: some AsyncSequence = llamaContext.startGeneration(for: prompt)
Task {
    for try await result in session {
        guard !Task.isCancelled else { break }
        guard case .piece(let newPiece) = result else {
            break
        }
        await MainActor.run {
            self.text += newPiece
        }
    }
}

パッと見、外からの使い勝手は良くなったように思えるが、結局Sequenceの内部はUnsafePointerの操作を隠蔽しているのであまり綺麗になっていない。

トークンは非同期に数文字ずつ生成されるので、Asyncに扱うための格好の題材だ。0からSequenceIteratorを書くことも少ないので、Mastering AsyncSequenceを読み直す機会にもなって良かった。

所感

Llama.cppとC++ interoperability

近年のSwiftでは、C++ interoperabilityがサポートされ、C++のライブラリもある程度そのまま扱えるようになってきている。一方で、現状のLlama.cppのSwift Packageは、PackageDescriptionが5.5と古く、C++ Interopを提供していない。そのため、実質的にはCインターフェイスしか読めず、UnsafePonterでAPIをゴリゴリと操作する必要がある。(つらかった)

Swiftパッケージ側をモダン化すれば、C++の構造体やクラスなどを直接Swift側で操作できるようになるので、ある程度使い勝手は良くなりそう・・・・・・。

Llama.cppのバージョニング問題

上記の AsyncSequence 化など、せっかく書いたので、もっとSwiftから扱いやすい形でライブラリを提供しようかと考えていたが、Llama.cpp自体に依存するのは現状危なそうに思えた。

Llama.cppにあまりドキュメントがないことに加え、semverを採用しておらず、今現在もドラスティックに実装が変更されているためだ。現に、最初に紹介した記事からわずか1年で多くの公開APIが変更されていた。

今回は学習のためのトイプロジェクトなので、メンテナンス性などを考え、一旦これ以上の発展を諦めた。

AppleデバイスとローカルLLM

開発の大部分はmacOS向けのビルドで行っていたが、実機(iPhone 16 Pro, iPad Pro(M4))でローカルLLMを動かしてみると、先述のELYZAのLlama 3モデルをはじめ、多くのLLMは純粋にメモリ不足で動かなかった。Llama3のモデルは4bit量子化のモデルしか提供されておらず、これが最小サイズなので、実機で動かすにはLlama 2.7のモデルを使うしかなかった。

実機のメモリに載るLLMでの実行。量子化しすぎるとアホになる

実機で利用可能なモデルは日本語だとご覧の通りの精度しか出ないため、実用にはほど遠い。その上、ユーザーに2GBものストレージも要求してしまう。汎用LLMは現時点では実用に耐えないだろう。

エンドユーザーからすると「スマホやタブレットにそんなにメモリいらんやろ」と考えていたけど、ローカルLLMをまともな精度で動かすには、現状、全くRAMが足りてないことがわかった。今年出たばかりのiPad Pro(M4)ですら8GB*2で全然足りない。

一方で、MacBookと同じチップを載せているiPadのMシリーズはもちろん、現行のiPhoneのAシリーズでも計算リソースは十分に見えた。計算量よりもRAMがボトルネックになっているのは直感に反していて面白い。

おわりに

休日1日 + αぐらいでLlama.cppの実装を読んだり、LLMについて簡単に学べた。特に、現状だとやはりオモチャ以上には使い物にならないという点が肌感を持って理解できたのは良かった。

LLMについても、現状の限界や、形式・量子化の手法など、いくつかキャッチアップすることができた。とはいえ、僕は機械学習については素人なので、肝心なモデルがどのように学習されているか、という部分については全く知識がない。この辺がブラックボックスになっているのは危ういなと感じつつも、全ては押さえきれないなという気持ちもある。

体験としては、3Dモデリングができずとも、Unityを使って拾ってきた素材でなんとなくゲームができるといった感覚に近かった。

Llama.cppの習得については、上記の記事以外にほとんど情報がなく、ドキュメンテーションも乏しいので、この記事が興味のある方の役に立てば幸い。

*1:簡単にとは言わない

*2:1TBモデルでは16GB搭載しているらしいので動くかもしれない。誰か試してみてほしい

実録・モバイルアプリ領域の技術顧問は何をやっているか

これまで僕は何社かのiOS領域での技術顧問を引き受けてきた。技術顧問というと、Xで怪しいアカウントが「50社歴任!週末副業で楽に稼げる!」などと喧伝していることがあったり、いかがわしいイメージを持たれている方もいるかもしれない。

過去4年以上に渡って技術顧問を務めてきて「一旦何をやっているんだ」と聞かれることは多かったが、ちゃんとまとめていなかったので、この機会に記録しておく。

これまでの技術顧問

これまで僕は3社で技術顧問をしてきた。ちなみに本記事では各社名の敬称は省略している。

  • taskey株式会社(2020/3~2023/7)

  • 株式会社マネーフォワード(2021/3~)

  • 株式会社ユビレジ(2022/8~)

それぞれ、中の人の推薦をいただき声をかけていただいた。ありがたい限り。

各社での動き方と役割

これまでご縁があった組織は、規模もフェーズも三社三様だ。最初に顧問を引き受けたtaskeyは社内の開発者も少人数の組織だったが、マネーフォワードは誰もが知るようなメガベンチャーだ。そうなると、顧問先により、当然求められている動きは変わってくる。

基本仕様として、質問応答、個別の技術相談や、SwiftやiOSの最新情報共有は変わらず行っているが、あとは求められていることや、組織のキャラクター性によって細かくカスタムしている。ちなみに、時間も限られているため、直接のプロダクト開発はお断りしている。概ね、以下のような役割を心がけて動いていた。

taskey株式会社

taskeyはWebtoonやチャット小説アプリpeepを展開するスタートアップだ。僕が顧問を引き受けた2020年当時、事業の拡大に対してエンジニアリソースが足りず、外部の開発力に頼る必要があった。その一方で、コード品質の低下やレビューが間に合わないといった成長痛ともいえる状況になっていた。また、フルタイムで働くメンバーとしてもシニアなエンジニアが少なく、適切な仕様の議論や、壁打ち相手がいないという問題もあった。

そこで、技術顧問として入り、レビュープロセスや自動化フローを整備したりメンバーのメンタリングなどの支援も行った。

一番最初に顧問を務めた組織で、手探りなことも多かったが、結果としてわりと長く続けることができた。CTOやメンバーとも信頼関係を築けていたと思う。典型的なスタートアップの課題を体感でき、大きな組織でしか働いたことがない僕には刺激的だった。

  • コーディングガイドラインの整備や委託先へのレビュー品質の向上
  • 自動化やCI、開発環境整備の支援
  • プロパーのメンバーのメンタリング、ペアプロ

株式会社マネーフォワード

対して、マネーフォワードは既に成熟した組織であり、プロダクトの開発や組織作りに直接僕が関わることはない。そのため、社内メンバーの支援を強く意識して動いており、いわゆるDeveloper Success的な活動も重視した。

転機となったのは、メンバー向けに行ったオープンソースSwiftのワークショップだ。

当時はコロナ禍で、社内メンバーが顔を合わせる機会も少なかったが、ワークショップのおかげでチームビルディングにも貢献できた。この機会が好評だったので、後にシリーズ化され、今でも半年に1度ほどのペースでオフラインワークショップを開催している。特にWWDCのrecapは、ただこちらから話すだけではなく、メンバーにまとめてきてもらう形式にした。

また、毎年入ってくる新卒やジュニアなメンバーにコミュニティとの関わりを持ってもらったり、登壇支援もしている。彼らをタレントとして輩出していくことで、本人のキャリアアップや、組織のプレゼンス向上に一役買えたと思う。

  • 個別の質問応答や設計レビュー、相談
  • 社内勉強会・ワークショップの開催による社内コミュニティ強化の支援
  • メンバーの登壇やキャリアアップの支援

株式会社ユビレジ

ユビレジはiPadのtoB利用をかなり初期から行っている老舗のレジアプリだ。一方で、老舗ゆえに、古いコードベースや技術的負債を抱えてしまっている側面もある。僕は前職でObjective-Cの破壊や、リアーキテクチャに取り組んでおり、その分野に一家言あるため、顧問を務めることになった。

かなり古くからあるアプリゆえ、最新の開発トレンドから少し取り残されてしまっていた部分があった。また、最近は古代言語ObjCに精通しているエンジニアも減っており、採用の問題もあった。

そのため、ユビレジでは古いコードベースの書き換えの促進や、リアーキテクチャの支援を中心に行っている。また、マネーフォワードほどの規模ではないが、ある程度の開発組織があるため、最新情報の知見共有会などもこちらから持ちかけている。

  • 採用やスクリーニングの監修
  • 技術的負債の解消の支援
  • リアーキテクチャや仕様策定のための壁打ち、技術相談

技術顧問としてパフォーマンスを出すために

こうしてまとめてみると、我ながら単なる業務委託に収まらず、わりと顧問っぽいことができていると思っている。ここからは、顧問を続けてく上で心がけていることを紹介する。

話しかけやすい環境を作る

まず、技術顧問のアンチパターンとしてありがちなのが「何かあったら聞いてください」と質問を受け付けるが、誰からもアクションがないケースだろう。結果的に「お願いすることがありませんでした」と言われ、うまく貢献できないことを心配している。

これは当然、いきなり入ってきた顧問に対してどんどん質問ができる人はそう多くない。少なからず遠慮もされていると思う。そのため、まずはメンバーとの関係構築をとても重視している。マネージャーやテックリード級の人と握るだけではなく、各メンバーにも話しかけてもらいやすいようなウェットなコミュニケーションを心がけている。1度話しておくと質問をしてもらいやすいなと感じるので、単純接触効果みたいなものは間違いなくあると思う。

これに近い話は、過去にマネーフォワードのインタビューでも述べている。

こちらからネタを提供し続ける

上記に加え、先方からアクションがない場合も、定期的にこちらから活動の提案をしている。iOS分野では、毎年WWDCや新しいOSが必ず出るため「recapをさせてくれ」というのはとてもやりやすい。自身のキャッチアップにもなり、かつ他の顧問先や外部登壇でも使い回しやすいので都合が良いという事情もある。

また「何か課題ありませんかね?」という雑なオープンクエスチョンも重要ではあるのだが、都度、トレンドに沿った質問もしている。「新しいXcode出たけど対応大丈夫ですか?」とか。

これはある種の「仕事してますアピール」でもあるのだが、何も仕事がないと不安になってしまうので、こちらからグイグイ行ってしまう。

顧問を専業にしない。本業との相乗効果を意識する

顧問は副業としてやることを心がけていて、顧問を専業にするつもりはない。一番の理由はメインの業務に責務を持っていないと、顧問として提供できるネタがなくなってしまうため。本業ではかなり特殊なことをやっているので、そこから得られる知見はとても大きい。

これは、穿った見方をすると、本業の切り売りと思われてしまうかもしれないが、決してそうではない。逆に顧問業から得ることも本業に生かし、シナジーを意識すべきだ。

本業の組織がデカすぎ、かつ業務が専門的すぎるので、どうしても普段やっていないことは一切触れずに手薄になりがちだ。顧問先で必要になり調査することで、それが本業に生きることも多い。

モバイル分野の顧問業をスケールしていくために

技術顧問としての経験は、キャリアの幅を広げる上でとても役に立っているし、何よりいろいろな人に感謝してもらえて嬉しい。できれば少しでもいろんな組織に役立ちたい。

そこで、依頼を増やすためにモバイル分野の技術顧問が必要な顧客のペルソナについて考えている。以下のようなパターンが多いだろう。

  • iOS/Androidのモバイルアプリをリリース・維持していく必要があるが、社内リソースがない
  • 人を増やそうにも、モバイル固有の技術やトレンドに知見がある人がいないので採用やスクリーニング、育成ができない

こうして考えていくと、基本的にiOSのみを主戦場としている僕ができることは結構限られている。

世の中の多くの組織が頭を悩ませる問題は、モバイルエンジニアの採用の難しさと、iOS/Androidへの二重投資だろう。1枠で兼ねられた方が都合が良いので、ネイティブアプリではなくFlutterを採用するのも頷ける。そのため、片方のプラットフォームに偏重したスキルセットは、顧問をやる上で広がりを持ちづらいように感じる。ほとんどの事業はクロスプラットフォームが前提になるので、それぞれに技術顧問を置くのは大変贅沢なことだ。

これまでの僕の顧問先は、分野毎に潤沢に技術顧問を置けるメガベンチャーのマネーフォワードや、主力製品をiOS/iPadOSのみに展開しているユビレジなど、実はかなり珍しい。今後もこういったご縁に恵まれるのが理想だが、スケールしづらいので、今後の展開のために何ができるかは少し考えている。

「二刀流」になるため、限られたリソースをAndroidネイティブやFlutter、Kotlin Multiplatformにステ振りしていくこともできるが、それが正解とも言えない。果たして浅く広い習熟で、実態を伴った顧問業ができるのだろうかという懸念はある。当たり前だが、なんでもは熟達できない。今ぐらい一芸に秀でている方が独自性もあるし。

ぶっちゃけ、顧問業を増やすことは主目的ではないので、そこまで環境適合していく必然性があるかは疑問がある。さしあたり、今後の戦略として、専門家にはなれずとも、AndroidやFlutterのコミュニティにも足を運ぶことはしてもいいのではないかと思っている。

技術顧問のお仕事募集中です!

この記事で「なんか技術顧問って怪しそう」というイメージが払拭できていたら幸い。そしてこの記事を書いたのは振り返りの意味もあるが、当然、僕の技術顧問業の宣伝という側面もある。

技術顧問はどんなにちゃんとやっていても、いずれは終わりが来てしまう。幸い、各社共にある程度長期に良好な関係が築けているが、それであっても顧問先の組織や事業の変化などにより、未来永劫つづけられるものではない。それゆえ、継続性を持たせるために常に新たなポジションを探し続ける必要がある。

顧問の需要自体はあるけれど「仕事を募集中かわからない」「実際ちゃんと働いているのか不明」という点でマッチングに繋がっていなかったこともあるかもしれない。大丈夫です、募集してます

この記事を読んで「怪しくなさそうだから任せても良いな〜」という方がいたら、ぜひ連絡をいただけると嬉しい。

『エンジニアチームの生産性の高め方』絶賛発売中!

この記事に書いた心構えの一部は、先日出版した『エンジニアチームの生産性の高め方』の中でも一部触れている。もしご興味を持ったらぜひお手にとって欲しい。

giginet.hateblo.jp