まずはできたもの
要約
タイトル生成
文章は下記の記事の内容となります。
OpenAI・Anthropic互換APIを無料で使おう!「さくらのAI Engine」3,000リクエスト使い切りチャレンジ - Qiita
概要
- さくらのAI EngineとOpenCodeを組み合わせて、SwiftでiOSアプリを作成してみる
- iOSアプリの要件
- Apple Intelligenceを使用したアプリにする
- 音声入力での文章作成、Apple Intelligenceの要約・整文機能を利用する
- データはローカルにのみ保存する
- これらを2週間で実装してみる
大まかな流れ
今回は作れるところまでを見る関係で、テストフェーズ等は割愛しています
1. さくらのAI EngineのAPIキー取得
下記を参考に、APIキーを取得します。
APIキーは漏洩しないように管理してください。
2. OpenCodeとさくらのAI Engine接続
今回は、プロジェクト配下に専用のopencode.jsonを作成します。
{
"$schema": "https://opencode.ai/config.json",
"provider": {
"sakura": {
"npm": "@ai-sdk/openai-compatible",
"name": "Sakura AI Engine",
"options": {
"baseURL": "https://api.ai.sakura.ad.jp/v1"
},
"models": {
"gpt-oss-120b": {
"name": "gpt-oss-120b"
},
"preview/Kimi-K2.7-Code": {
"name": "Kimi-K2.7-Code-Preview"
}
}
}
}
}
さくらのAI Engineは、OpenCodeのProviderには登録されていません。
そのため、/connectでは接続せず、opencode auth loginを使用します。
- provider:
other - provider id:
sakura - API key:事前に発行したさくらのAI EngineのAPIキー
設定後、opencode auth listを実行します。
下記のように表示されていれば、接続完了です。
% opencode auth list
┌ Credentials ~/.local/share/opencode/auth.json
│
● sakura api
│
└ 1 credentials
3. Xcodeプロジェクト作成
Xcodeを使用する上で、1から実装するのはプロジェクトが破綻する可能性があります。
そのため、はじめに最小構成を作るための手順を作ってもらいました。
提示された手順でXcodeプロジェクトを作成して、事前準備は完了です。
4. 実装計画書作成
作ってみたいものは、大まかにイメージをしていますが、それをAIに伝える必要があります。
- iOS / iPadアプリ
- Apple Intelligenceを使って、音声入力した文章を要約したり、文章整形したい
- ダークモードは必須で、データはローカルJSONファイル保存のみとして、外部に送信しないようにしたい
- 実装のフェーズの切り方は、そのフェーズを完了したら特定の機能が使える状態とする
これらを条件として、AIとディスカッションして要件を詰めていき、実装計画書を作成してもらいました。
## 1. 前提・制約
| 項目 | 内容 |
|------|------|
| 対応 OS | iOS 26 以上 |
| 対象デバイス | iPhone / iPad ユニバーサル(Apple Intelligence 対応端末のみ AI 機能を有効化) |
| 言語 / フレームワーク | Swift 6、SwiftUI |
| アーキテクチャ | MVVM(`Views/`, `ViewModels/`, `Models/`, `Services/`) |
| UI 要件 | ダークモード必須、独自デザイン資産なし(SwiftUI 標準コンポーネントで作成) |
| 永続化 | ローカル JSON ファイル保存のみ |
| 外部送信 | 音声・文字起こし内容を外部へ送信しない |
| AI 機能 | 要約・整文・タイトル生成(Apple Intelligence) |
| 締め切り | 8/22 までに動作する MVP 完成、8/25 Qiita 記事投稿 |
---
## 2. フェーズ別作業一覧とマイルストーン
中略
### 7️⃣ ローカル永続化(JSON ファイル保存)
- **主なタスク**:
- `Draft.swift` モデルを作成(`id`, `content`, `createdAt`, `updatedAt`)
- `FileStorageService.swift` を作成
- `FileManager` で `Documents` フォルダに JSON 保存・読み込み
- アプリ起動時に未保存ドラフトを自動復元
- **完了時の状態**: アプリ終了 / 再起動後も直前のテキストが復元される。
中略
---
## 3. 実装上の重要ポイント
### 3.1 Apple Intelligence の有効化判定
```swift
if #available(iOS 26, *), AIService.isAvailable {
// AI ボタンを有効化
} else {
// AI ボタンを無効化し、理由を表示
}
```
### 3.2 ダークモード対応
- `ColorAssets.xcassets` で「Any, Dark」バリアントを設定
- `TextEditor` 背景は `Color(.systemBackground)` を使用
省略
5. 実装実施
作成した実装計画書をもとに、AIに作成していきます。
基本的には下記のプロンプトで実装を指示しました。
Phase 7の実装を進めてください
フェーズを機能単位で切るようにしているため、上記で各フェーズの実装完了まで実施してくれます。
以降は、Xcodeでプロジェクトを開いて実機ビルドした結果を見ながら、修正指示を投げていきます。
フェーズの実装が完了したら、下記のプロンプトでやったことをまとめてもらいます。
Phase 7で実装した内容を phase7.md にまとめて
# フェーズ 7 — ローカル永続化と内容ベース AI ロジック
## 目的
- 音声認識・文字起こし結果を **ローカルに保存** し、アプリ起動時に自動復元できるようにする。
- 「要約」「整文」「タイトル生成」ボタンが **実際の文章内容** に基づく処理を行うように AI アルゴリズムを改善。
## 追加・変更したファイル
| ファイル | 変更概要 |
|---|---|
| `Models/Draft.swift` | `Draft` モデル(`Identifiable`, `Codable`, `Equatable`)を追加。 |
| `Services/FileStorageService.swift` | JSON でドラフトの **保存・読込** を行うサービス実装。 |
| `ViewModels/VoiceDraftViewModel.swift` | - `storage` と `drafts` プロパティを追加。<br>- `init()` で保存済みドラフトをロードし、最新の内容を `finalText` に設定。<br>- `saveCurrentDraft()` を実装し、現在のテキストを `Draft` として保存・リスト更新。 |
| `Views/MainView.swift` | **保存ボタン**(緑)を UI に追加し、`viewModel.saveCurrentDraft()` を呼び出すようにした。 |
| `Services/AIService.swift` | - `sentences` を `let` に変更し警告解消。<br>- **要約**: 単語頻度でスコア付けし上位2文を抽出。<br>- **タイトル生成**: 文分割→単語頻度→スコア付けで最重要文から先頭5語を抽出しタイトル化(先頭文字大文字化)。
## ビルド結果
```
$ xcodebuild -scheme VoiceKeyboard -project VoiceKeyboard/VoiceKeyboard.xcodeproj \
-destination "platform=iOS Simulator,name=iPhone 15 Pro,OS=26.5" clean build
** BUILD SUCCEEDED **
```
- すべての新規・変更ファイルがコンパイルエラーなしでビルド完了。警告 `Variable 'sentences' was never mutated` も解消。
## 動作確認手順
1. **アプリ起動** → `FileStorageService` が `drafts.json` を読み込み、最新ドラフトが `finalText` に表示される。
2. 録音・文字起こし → テキストがエディタに表示。
3. **保存** ボタン → 現在のテキストが `Documents/drafts.json` に保存。(`Draft` が作成・更新される)
4. アプリ終了・再起動 → 保存したテキストが自動で復元される。
5. **要約** ボタン → 内容に基づく重要な2文が抽出されて `finalText` に置き換わる。
6. **整文** ボタン → 改行・余分空白が整理され、句点で終端したテキストが得られる。
7. **タイトル生成** ボタン → 本文全体を解析し、最も重要な文から先頭5語を抽出した適切なタイトルが `finalText` に設定される。
## 次のステップ(Phase 8)
- **テスト追加**:`FileStorageService` と `VoiceDraftViewModel.saveCurrentDraft()` のユニットテストを実装し、保存/復元ロジックを検証。<br>- `AIService` の要約・タイトル生成ロジックのテストケースを作成(頻出語句やスコア付けが期待通りに機能するか)。
- **自動保存**:文字入力や音声確定時に自動でドラフトを保存する仕組みを検討。
- **UI フィードバック**:保存成功/失敗のトースト表示や、ドラフト一覧画面への遷移を実装。
- **本格 AI 連携**:最終的に Apple Intelligence (`SystemLanguageModel`) へ差し替えて高度な要約・タイトル生成を行う準備。
つまづいたところ・苦戦したところ
Xcodeでのエラーを吸収できない
Xcodeでエラーが出ていた際に、エラーメッセージの内容を伝えて修正を依頼しましたが、修正完了の回答に対してエラーが残っている場合がありました。
「エラーが出ないことを確認して完了として」の旨のプロンプトを追加しても残る場合があったので、ここはもう少しプロンプトを詰める必要がありそうです。
Xcodeプロジェクトが壊された
実装を依頼後、確認のためXcodeプロジェクトを開こうとしたら、エラーで開けない事態が発生しました。
こちらもエラー内容を伝えて開けるように修正が走りましたが、いくつか不備が出てしまい、結局1つ前のフェーズのコミットに戻ることとなりました。
ガードレールをきちんとすべきだと、改めて実感させられる一幕でした。
前フェーズ実装した機能が、次フェーズ実装時に意図しない変更が起こった
前フェーズで実装していた機能が、次フェーズの実装完了時のテストで、機能が正常に利用できなくなることが何度か発生しました。
こちらは現状の挙動を都度伝えて、機能を戻す作業を何度か繰り返すことで対応しましたが、こちらもプロンプト等をきちんとすべきでした。
成果サマリ
この文章の構成等も依頼している関係で、少しリクエスト数がずれていますが、おおよそ1000リクエストで上記のようなアプリを作ることができました。
入力トークン数で見ると、約40Mトークンとなり、他のコーディングAPIでの従量課金を考えると、いかにコストパフォーマンスに優れているかがわかります。
終わりに
今回の実装では、基本的な機能の実装はできましたが、アプリアイコンやスプラッシュ画面の実装などは未実装となっています。
最後のアプリ申請以外まで任せるには、ユーザ自身の使い方も学んでいく必要があります。
しかしながら、リクエストベースでカウントされるということは、トークン量が多くなりがちなドキュメントを読み込ませた上で開発させる点では、さくらのAI Engineがかなり優れていると言えます。
月3000リクエストは無償で利用できるので、1度使用してみてはいかがでしょうか。



