🎉

[Flutter] サブスク有りのAI会話の語学アプリを開発した話(技術スタック公開)

2024/09/30に公開

はじめに

よく個人開発で見かけるのは

・サウナのアプリ
・ラーメンの場所を検索するアプリ
・生活アプリ

こんなところでしょうか(笑)
ですが、言語アプリもとっつきやすくて個人開発にオススメです。

そんな、語学アプリ開発や、個人開発に、役立ちそうな開発の流れや、パッケージを一挙に公開しようと思います。

ターゲッティング

  • 言語アプリはダウンロードが比較的入りやすい

  • 英語はレッドオーシャン

  • 韓国語は単語アプリなどは充実しているが、会話アプリはストアにあまりない

  • 自分が韓国語の知識を有している

  • SEOキーワードで『韓国語アプリ』と検索すると、『ai』や『会話』がヒットするので、ここを狙おう

  • 旅行なども入ってきているから、シチュエーションとかけられそうだな

こんな感じで、始めました。

あと、ターゲットですが、

  • 旅行する準備でチョット言語を学習しておきたい人
  • ワーホリ準備で生活会話を学習しておきたい人

といった、現地での会話をシュミレーションしてる人としました。

どんなアプリか

ざっくりまとめると、ホテル、タクシー、食事といった様々なシチュエーションでの会話を想定したAI会話アプリです。
こんな感じで、音声かメッセージでGptにリクエストを送信して、翻訳を添削してもらう感じです。

言語

Flutter

本業で多用している言語です。
なんといっても、クロスプラットフォームがいいですよね。
昔は、Swift を書いていましたが、Flutterが個人アプリでは、しっくりきます!

ですが、最近googleのテスターによる審査が厄介なのでGoogleStoreには申請を出していません。

ちなみに、ココナラとかでテストをしてくれるサービスがあるみたいですね。

1ユーザ1アカウント制限の認証(退会)

Firebase Auth

サブスクリプションで3日間のトライアルを提供していますが、これを何度も利用されるのは問題があるため、1ユーザにつき1アカウントの制限を設けることにしました。そのため、ログインにはGoogleやApple認証を使用し、サインアップ時に電話番号を紐づける方針としています。これにより、同じユーザが複数のアカウントを作成して繰り返しトライアルを利用することを防ぐことができます。

また、退会後に何度も登録されないように、14日間のインターバルを設けました。

ざっくりとフローは以下です。

DB

FireStore

普段は、RDBMSを利用していますが、NoSQLを利用しました。
トランザクションをがんがん入れていく感じのアプリではないので、こちらが個人アプリには最適です。
とりあえず、リリースまで最速で持っていきたいって人は、FireStoreがいいですよね!

サーバー

Cloud Functions

  • サインアップされたけど、メールアドレスや 電話番号の認証が終わっておらず、一定期間放置されているアカウント。

  • 退会して14日が経過したユーザ情報。

これらは、cloud Fucntionsで自動的に削除する方向にしました。

サブスクリプション実装

以下を使用しました。
Stripeなどもつかったことがありますが、こちらの実装は楽でおすすめです。

https://www.revenuecat.com/jp/?utm_source=google&utm_medium=cpc&utm_campaign=jp_branded&utm_content=jp_branded_exact&utm_ad=696703084714&utm_term=revenuecat&matchtype=e&device=c&GeoLoc=1009310&placement=&network=g&campaign_id=21164410974&adset_id=160064600799&ad_id=696703084714&gad_source=1&gclid=Cj0KCQjwr9m3BhDHARIsANut04Y_dTd8GgXt5pEQVwNwlDb0LrSEK-ABscqL70J7ASAjOvTiOUm-AuUaAnlcEALw_wcB

使える 3rdパーティライブラリ

音声 → テキストに変換

割と正確に聞き取ってくれるのでオススメです。
変換ミスは、手動で訂正する方針としてます。

https://pub.dev/packages/speech_to_text/example

テキスト読み上げ

  • 音声の速度変更
  • 声が登録されていれば音声変換が可能(言語によっては女性ボイスだけなど)

と、単語や文章の読み上げに大変便利です。
https://pub.dev/packages/flutter_tts

DeepL翻訳

アプリ内でDeepLの翻訳が使えます。
APIキーが必要です。
以下のように、シングルトンオブジェクトとして活用すると翻訳機能が充実します。

import 'package:deepl_dart/deepl_dart.dart';
import 'package:flutter_dotenv/flutter_dotenv.dart';
import 'package:riverpod_annotation/riverpod_annotation.dart';
part 'deepl_provider.g.dart';

@Riverpod(keepAlive: true)
Translator translator(
  TranslatorRef ref,
) {
  return Translator(authKey: dotenv.get('DEEPL_KEY'));
}

https://pub.dev/packages/deepl_dart/install

OpenAI

こちらも、OpenAIのAPIキーが必要です。
こちらは、翻訳を添削してもらうために使います。

解答例を示すだけにしようとしましたが、他のアプリとの差別化を図るためにAIを導入したかったのと、ユーザの回答が間違っている場合、どんな回答になってしまうのかといった観点で添削するために使用しました。

https://pub.dev/packages/dart_openai

てがるに素早く使える デザイン

ちょうどいいイラスト

こちらは、Youtubeの挿入イラストでもよく見かけます。
商用利用可能で、カジュアルに使えるのがいいですね!
また、シチュエーションのセレクト画面で合いそうなデザインを適応させていただきました。

https://tyoudoii-illust.com/

icon8

AIが採点してくれている時の、Loadingの画面のロボットのが動いてるデザインに使用しました。

https://icons8.jp/icons

プレミアムプラン(サブスク登録)

AIの性能や、問題のレベルに制限をかけてプレミアムプランで開放する方針としました。

機能 無料 プレミアム
チャレンジできるレベル 初級のみ 無制限
AI Gpt-3.5 Gpt-4o
広告非表示 ×
DeepL翻訳
音声の速度変更

一番の目的は、Freeプランでは挑戦できる問題のレベルに制限をかけてタップされたらサブスクの画面に誘導することです。

AIを使うことで苦労したこと(LLM)

翻訳なので、正解には様々なバリデーションがあります。正解の解答例と比較すると、それ以外の翻訳をAIが正解として認識しなくなってしまうことがあります。

そのため、まずは翻訳が意味として通じるかを判断させ、その後に文法チェックを行い、違和感がある場合は解答例と照らし合わせながら添削するという流れにしました。これにより、異なる表現でも意味が通じるかを見てくれるようになりましたが、まだまだ改善の余地があり、全然完璧ではありません。使いながら改善する必要があります。

やはり順番が大事ですね。この辺りはLLMの知識に関わる部分でしょうか。今後のためにも、しっかりキャッチアップしていく必要があると感じています。

今後の対応

  • 無料プランの場合は、チャレンジできる問題数に制限をかける(例えば1日10回までとか)。
  • シチュエーションを増やし、問題の充実。
  • ユーザーからフィードバック対応。
  • LLMの精度向上。

を意識しながら、いろいろ改善していければと思います。

最後に

改めて、利用規約の整備や退会処理など、追加していくべきことがたくさんあるなと感じました。しかし、Flutterを使った開発は非常に効率的で、面倒に思うことなく楽しく進めることができました。

今後は、さらに市場調査やマーケティングスキルの向上にも力を入れていきたいと思いました。

Discussion