Blog

2024.10.28

Engineering

グループ開発: あなたの理想を叶えるコーチアプリ「Task Coach」

Yura Aoyama

はじめに

本記事は、2024年夏季インターンシッププログラムで勤務された相園さん、荒木さん、安藤さん、佐藤さんによる寄稿です。

Preferred Networksでは、8/26〜9/20の4週間、2つのテーマでグループ開発インターンを実施しました。
サービス開発を行うテーマでは、多様なバックグラウンドを持つ10名の学生に3つのグループに分かれて参加していただきました。

今回のお題は「LLMをチャット以外の形で活用したアプリケーション」でした。メンターのアドバイスの下、インターン生自身がアイディアを出し、ブレストを行い、協力しながらサービスを実装しました。

本記事では、チームCが開発したアプリについてご紹介します。

 

アプリケーション名、概要

我々はTask Coachというアプリケーションを開発しました。
Google Calendarの空き時間を考慮し、ユーザーが目標達成に必要なタスクを LLM が自動で生成します。また、ユーザーのタスク達成度から、LLMが取り組み状況に対してフィードバックをくれます。

 

アプリのねらい

Task Coachは、目標があっても自力で努力を続けていくことができないという課題を解決するアプリです。
「英語を話せるようになりたい」や「専門外のテクノロジーにも詳しくなりたい」などの目標は、達成しなければならない期限等がなく自分に委ねられています。こういった目標は、日々やることに追われていると後回しになり達成できないという人は多いのではないでしょうか。しかしこのような目標こそ、達成することで生活が豊かになるのではないかと我々は考えました。

Task Coachはユーザーの目標に合わせてユーザーがやるべきタスクを生成し、その達成度に応じたフィードバックを提供するアプリケーションです。タスクを行う時刻までアプリ側で指定することでユーザーが取り組みやすく、またユーザーの好みに合ったキャラクターが激励してくれるためモチベーションの促進へ繋がります。

機能紹介

以下がログイン画面です。Google OAuthのシステムを採用しており、ユーザーは自身のGoogleアカウントを選ぶことでログインすることができます。

以下がログイン後に画面遷移するユーザー登録画面です。
ここで自分の達成したい目標や、1日の中での活動可能時間、コーチの厳しさを選ぶことができます。

以下がユーザー登録後に画面遷移するトップページです。
右側にあるのがカレンダービューで、ログイン時に用いたGoogleアカウントで使っているGoogle Calendarから取得したタスクや、このアプリで生成したタスクが表示されます。
そして右下にある「タスク生成」のボタンを押すと、Google Calendarの空き時間やユーザーの活動可能時間を考慮し、適切な時間帯にタスクを自動で生成してくれます。
生成されるタスクの内容は、選んだコーチの性格によって異なります。厳しいコーチの場合は、過去に行ったタスクの中で達成度の低いタスクを再度生成するようにし、優しいコーチの場合は達成度の低かったものは避けるようにしてタスクを生成するようにしています。
左側のビューでは、日ごとの振り返りを行うことができます。
GitHubの草のようなイメージで、達成度が高いタスクが多い日はマスの色が濃い緑になります。

生成されたタスクは採用するかキャンセルするかを選ぶことができ、採用されたタスクは、それぞれ右側のサイドバーでタイトルや時刻の変更ができます。また、そのタスクについて自由にメモを書くこともできます。
さらに、コーチからそのタスクについてのサマリーをもらうこともできます。このサマリーは、そのタスクのタイトルや時間帯、メモの内容を元に生成されています。

左側のビューに並んでいるマスを選ぶと、その日について振り返りができます。コーチからコメントを貰ったり、1日を振り返ってもらうことができます。

ここで、コーチの性格を変更して1日を振り返ってもらいました。口調が変化しているのが分かります。
画面右上に表示されている自身のGoogleアカウントのアイコンをクリックすることで、ユーザー登録時に入力した全ての項目を変更することができ、コーチを変更することもできます。

 

技術的・開発プロセス的アピールポイント

技術的アピールポイント

1.  技術スタック

開発は以下のような技術スタックを用いて行いました。

フロントエンド
Reactで開発を行い、ビルドツールはViteを使いました。


また、UIライブラリとしてMantine UIを採用し、カレンダーのUIを表示するためにFullCalendarを使いました。
FullCalendarで提供されているカレンダーUIは我々の理想のものとは異なり、修正を加える必要があったためstyled-componentsによってスタイルの拡張を行いました。

バックエンド

フレームワークはFastAPI、DBはPostgreSQLを用いて開発を行いました。
Pythonは動的で型付けが弱いことで知られていますが、我々はPydanticを用いることでSQL Alchemyのモデルとの互換性を取った上で、リクエストとレスポンスの型を定義して、ある程度型安全にAPIを構築することができました。
またDatabaseのマイグレーションツールとしてAlembicを使用しました。AlembicはSQLAlchemyのモデルを修正するとその変更を読み取って、マイグレーション用のrevisionを自動生成してくれます。
これは、開発を進めてDBのスキーマが変わったと同時にマイグレーションのリビジョンが完成することを意味します。

Dockerのコンテナ起動時に生成されたリビジョンファイルから最新のマイグレーションを当てて、初期データの挿入までも行うことができるので、コンテナの破棄やDatabaseの作り直しを気兼ねなく行うことができ、開発をスムーズに進めることができました。

2. Dockerとデプロイ

我々のチームは開発の段階からDockerを導入して、チーム全員が同じ環境下で開発できるようにしました。Dockerを導入することで、チームメンバー誰かがエラーに遭遇しても環境の違いを気にする必要がなくなり、問題を切り分けやすくなります。

また、Database内のデータを永続化しておくことで、開発をスムーズに進めることができました。Dockerを開発の初期段階から導入したことで、デプロイもスムーズに進めることができました。我々は成果物をfly.ioにデプロイしましたが、fly.ioにデプロイするにはDockerのイメージをpushする必要があります。プロダクション用と開発用にDockerfileを多少修正する必要はあるものの、Dockerfileの雛形が揃った状態でデプロイに進むことができたのは、非常に大きなアドバンテージになったと思います。

3. 認証周りとセッション管理

我々はGoogle Calendarに登録されている予定をアプリ内に表示するため、認証をGoogle OAuthを用いて行いました。

認証まわりを色々よしなにやってくれるサービスといえば Firebase が挙げられますが、今回はPythonのGoogle OAuth Libraryを用いて自前で認証フローを実装することにしました。Google OAuthを用いた実装では Access Token の期限が切れた場合には再度トークンを発行する必要がありますが、トークンの期限が切れる度にユーザにログインを求めるのはユーザ体験を損ないます。そこでリフレッシュトークンを用いたアクセストークンの自動更新を認証フローの中に実装しました。(下図参照)


また、サーバに飛んできたリクエストが認証済みのユーザによって行われたものなのか、トークンは有効かなどを判定する認証ミドルウェアも実装しました。

このミドルウェアはユーザー登録以外の全てのAPIを叩く際に適用されるため、認証を受けていないユーザや不正に取得したトークンを持つユーザはAPIを叩くことができません。このような認証ミドルウェアを実装することで不正なログインを防ぐと同時に、Google OAuthを用いた認証を実現することができました。

4. StreamingとStructured Outputsの活用

今回使ったOpen AI APIについても活用方法について工夫点があります。 まず、コーチからフィードバックや振り返りをもらう機能については、テキストをStreaming形式で受け取りUIに表示するようにしました。こうすることで、応答時間を短縮し、実際にコーチとやり取りをしているかのような臨場感を演出することができました。また、Structured OutputsによってAPIからデータを扱いやすい構造で受け取るようにしました。

5. LLMのプロンプトチューニング

今回、LLMを使っているのはタスク生成およびコーチからのサマリーやフィードバックを生成するところです。
タスク生成については、実際にユーザーが取り組みたくなりモチベーションを保ってもらえるようなタスクを生成できるように工夫しました。そのタスクに取り組む上で参考となる教材やWebサイトの名前も出すようにし、具体性を持たせるようにしました。さらに、ユーザーが過去に取り組んだタスクの内容を与えることで、ユーザーのこれまでの取り組み状況を考慮してタスクを生成するようにしました。

また、コーチからのサマリーやフィードバックを生成するところでは、コーチに性格を持たせるように工夫しました。キャラクターの背景や話し方、目指すべき理想やビジョンをプロンプトに与えることで、親しみやすいキャラクター性を持たせました。

 

開発プロセス的アピールポイント

  1. GitHub を中心にしたタスク管理
    定期的な issue 管理や細かい PRによってスムーズに開発を行うようにしました。また、レビュー作業を個々人のタスクより優先することでチーム全体での時間のロスを縮めるように心がけました。
  2. 綿密な情報共有
    現状の問題とこれから何をするのかを1日2回以上メンバーと共有するようにしていました。また、実装する機能の決定などチームで意思決定をする必要が生じたときは、積極的に時間をとって議論をするようにしました。
  3. フィードバックを積極的にもらうようにした
    我々だけでは気づけない点について、メンターの方から客観的なフィードバックをいただきました。それらを反映することで、アプリケーションを大幅にブラシュアップすることができたと感じています。

 

感想

チーム全員、楽しみながら開発に取り組み、充実した4週間だったと感じています。以下に良かった点を挙げます。

  • Google 認証の実装の大変さ、デプロイ作業の大変さを学べた
  • チーム開発でのアイデアの出し方、まとめ方を学べた
  • 限られた時間でやるべきこと/やるべきでないことを見極められた
  • フロントエンドとバックエンドの垣根を越えて作業ができた
  • 高いチームワークで快適に開発が進められた

メンターの青山さん、鈴木さんをはじめ、レビュー会でフィードバックをいただいた西澤さんや他のチームのメンターの皆様など、たくさんの社員の方々のサポートのおかげで充実した4週間を過ごせたと思います。本当にありがとうございました!

 

メンターからのコメント

遊び心がありながらも機能面で十分実用的な完成度の高いアプリだと思います。デザイン面でも最後までフィードバックに粘り強く対応して改善に取り組んでいただきました。

各々が明確な役割を持って建設的な議論を行い、良いチームワークで開発に取り組めたからこその成果だと思います。積極的に新しい技術に挑戦しようという姿勢が見られたのも素晴らしかったです。

みなさん4週間本当にお疲れ様でした! 

 

  • Twitter
  • Facebook