📖

【Flutter】 Clineと DeekSeek R1 で日記アプリを作ってみた

2025/01/28に公開

前回の記事の続きです。
今回は Cline 3.2.5、DeepSeek R1 (Reasoner)を使用しました。

前回からの変更点

この記事から読んだ方用

Flutterプロジェクトの作成

flutter create calendar_example --platforms=ios,android

無駄なファイルを削除

なるべくAIにノイズが混じらないように以下のファイルを削除します

  • analysis_options.yaml
  • calendar_example.iml
  • pubspec.lock
  • README.md
  • test/widget_test.dart

iosandroidディレクトリーも別の場所に退避しておきます。
これでファイルとディレクトリーは以下の三つだけになります。

  1. lib/main.dart
  2. pubspec.yaml
  3. test

main.dartpubspec.yamlを編集

main.dart
import 'package:flutter/material.dart';

void main() => runApp(MyApp());

class MyApp extends StatelessWidget {
  
  Widget build(BuildContext context) => MaterialApp(home: Scaffold());
}

pubspec.yamlには必要なパッケージをあらかじめ追加しておきます。
今回はカレンダーが中心の日記アプリなのでtable_calendarを使用。
保存は安定性があるのと、SQL文もちゃんと書いてくれるか気になったのでsqfliteを使用することにしました。

pubspec.yaml
name: calendar_example
description: ""
publish_to: "none"
version: 1.0.0+1

environment:
  sdk: ^3.6.0

dependencies:
  flutter:
    sdk: flutter
  cupertino_icons: ^1.0.8
  sqflite: ^2.4.1
  table_calendar: ^3.2.0

dev_dependencies:
  flutter_test:
    sdk: flutter
  flutter_lints: ^5.0.0

flutter:
  uses-material-design: true

lib以下にディレクトリー作成

今回の希望の設計になるようにディレクトリーを作成します。

lib
├── application
│   └── use_case
├── domain
│   └── entity
├── infrastructure
│   └── db
├── main.dart
└── presentation
    ├── component
    ├── inherited_widget
    └── page

プロンプト

Flutterで日記アプリを作成してください。

要件
・pubspec.yamlの編集は禁止です。既に追加しているパッケージのみを使用してください。
・ディレクトリーの新規作成は禁止です。libのディレクトリー構成に合わせたアーキテクチャーで作成してください。
・UseCase、Entity、StoreをViewに受け渡すにはInheritedWidgetを使用してください。
・書いた日記はカレンダーで日付ごとに読めるようにします。カレンダーは月単位、週単位で切り替えられるようにしてください。週単位では日記の内容が一覧で見れます。
・カレンダーの日付をタップするとカレンダーの下に日記を表示します。
・日記は編集と削除が出来ます。削除する時は確認ダイアログを表示してください。
・本日または本日より前であれば日記が作成できます。
・日記はsqfliteでdiaryテーブルに保存します。
・WidgetテストとUnitテストを行ってください。

上記のプロンプトをGPT-4oで英訳したものを使用します。

  1. iOSシミュレーターを起動しておく
    Clineと DeepSeek R1 はflutter runを自動で実行し、起動時のエラーログを基に改善することがあります。
    これに伴い、前回は削除していたiosディレクトリーを残しておきます。
    基本的にAndroidエミュレーターでも差はないと思いますが、iOSの方がログが少ないです。

  2. プロンプトは日本語のままで使う
    何度か試しましたが、英語と日本語でコード品質に差異を感じませんでした。
    ClineのログとアプリのUIが日本語になるという利点もあります。

  3. flutter pub getしておく
    pubspec.lockが無かったり古かったりしてもClineが自動で実行してくれるのですが、プロンプト代節約のために。

  4. テストコードは作らない
    テストコードを一緒に作らせると品質が良くないので、必要な時は別タスクとしてやらせることにします。
    なのでtestディレクトリーも削除します。

プロンプトは少しだけ微調整していますが、ほとんど変更なしです。

プロンプト
Flutterで日記アプリを作成してください。

要件
・pubspec.yamlの編集は禁止です。既に追加しているパッケージのみを使用してください。
・ディレクトリーの新規作成は禁止です。libのディレクトリー構成に合わせたアーキテクチャーで作成してください。
・UseCase、EntityをViewに受け渡すにはInheritedWidgetを使用してください。
・書いた日記はカレンダーで日付ごとに読めるようにします。
・カレンダーの日付をタップするとカレンダーの下に日記を表示します。
・日記は編集と削除が出来ます。削除する時は確認ダイアログを表示してください。
・本日または本日より前であれば日記が作成できます。
・日記はsqfliteでdiaryテーブルに保存します。

結果

なんと一回で完成品が出来ました。
DeepSeek R1 が作成した日記アプリその1

動作も問題なし。一ヶ月表示、二週間表示、一週間表示の切り替えも出来ます。
APIが混雑していなかったのか5分程度で作ってくれました。

入力12万2000トークン、出力6000トークンで$0.0389(155円換算で約6円)
少し前にR1で他のことをさせていたのでキャッシュが2万トークンほどありますが、それを加味してもあまり高くないですね。

ついでに2回追加で作ってもらいました。

DeepSeek R1 が作成した日記アプリその2
(日記の保存は上手くいかず)

DeepSeek R1 が作成した日記アプリその3
(保存はするが日付を変えると消えてしまう)

最初と違い不具合はありますがすぐに直せる程度のものでしたし、DeepSeek Chat のようにUIが壊れていることもないです。
プロンプトが短いのでUIに幅があって面白いですね。実装も読んでいて勉強になりました。

費用が何故安かったのか

R1とChatの料金は現在、プロンプトキャッシュが発生している時で10倍、していない時で約3倍、出力は約8倍の差があります。

前回の記事の通り、DeepSeek Chat でかかった費用は一回あたり$0.0111〜$0.048なのに対し、
今回の DeepSeek R1 は$0.03026〜$0.0719です。せいぜい2倍程度の差しかありません。

この理由はChatはエラーを解消するための修正回数が非常に多く、結果としてプロンプトが何倍にも膨れ上がってしまっているためです。
今回と同一条件でChatでも何回か試したのですが、やはり修正回数の多さは変わらず、むしろ解消できずに無限修正編が始まったことが一度あって怖かったです…。

おまけ:Claude 3.5 Sonnet でも作ってみた

Claude 3.5 Sonnet が作成した日記アプリ

Claude 3.5 Sonnet でも3回作らせてみましたが、特に品質に差異は感じられませんでした。日本語が丁寧になっている程度です。

お値段は10倍近く高いので、今回のように既存コードをプロンプトに含ませないのであればR1で良いかなと思いました。

おわりに

DeepSeek R1 でも一発で不具合なしの完成品を作ってくれることは少ないのですが、今回くらいのアプリなら数行〜十数行程度修正すればエラーなく動くことが多かったです。
いくつか作らせて、気に入ったUIやクラスを組み合わせるのが良い感じかなと思いました。

Clineを改造すれば起動後のスクリーンショットをGeminiに投げて自動で改善してくれたりとか、特に詳しく仕様を書かなくても統合テストを書いてくれたりも出来るのかも。夢が広がりますね。

GitHubで編集を提案

Discussion