Pocket

こんにちは。エンジニア的な仕事をしているハッカソン好きです。

先日、Yahoo! JAPAN Hack Day 2019というハッカソンに大学の時から一緒に出ているメンバーと4回目くらいの出場をしました。
流石に4年以上やっていると色々と洗練されてくるなと感じまして、ハッカソンで成果を出すポイントについてのまとめと、振り返りなどを通してよりハッカソンスキルを向上させていこうかなと思い記事を書いています。

まずはハッカソン当日をどのように動いていくかという振り返りを通して、要所要所のポイントを整理して、次に今回の全体的な振り返りをしてみようと思います。

ハッカソン当日の振り返り

ハッカソンの当日のちょっと前

ハッカソン出場が決まったので、メンバーで集まってご飯など食べながらアイディアについて話し合いをしました。
「AIの配信者を作って24時間配信させ続ける」というアイディアが出たので、こんな感じでやったらうまく実現できるかもとか、じゃあどんな技術が使えそうかねとかそういうことを話し「じゃ、当日までに各自技術調べたり考えたりしましょうね」という感じで当日を迎えます。

ハッカソン当日 スタート

ここからハッカソンの当日の様子を振り返ってみます。

作り物の要件出し

要件を書き出したりTODOリスト作ったり

「AIの配信者を作って24時間配信させ続ける」というアイディアですが、実際にシステムに落とし込む際には色々決めなければなりません。

このアイディアをさらに詳細に詰めて、「これを満たさないと完成とは言えない」という物をメンバー間で認識合わせします。
ただし、いつも一緒に開発を進めているメンバーなのでこの辺は雑に進めても何とかなるのが良いですね。

とは言え、以下のような要件になりました。

  • Webアプリケーションとしてハッカソン期間中に公開する
  • 架空の配信キャラクターを用意して、ある程度意味のあるトーク内容を24時間喋り続けるようにする
  • ユーザーは配信に対して入室やコメントといったアクションができる
  • ユーザーの入室やコメントを投稿できるようにして、それに対して、ある程度意味のある返答をリアルタイムにできるようにする

全体設計の作成

次にシステムの全体像設計とそれぞれのコンポーネントについてメンバー間で認識を揃えました。

system

今回作ったシステムの最初の設計図

ここが結構ポイントで、まずはじめにメンバー全員が並行して取り組めてかつ疎結合になるモジュールに切り分けることが重要です。
また、それぞれのインタフェース(どういう形でやり取りを行うか)を決めるとどこかのモジュールが完成していなくてもダミーデータで動作が確認できるので、他コンポーネントの詳細を知らなくてもなんとかなるというところが良いところです。

今回はコンポーネントの中でクラウドサービスであるpub/sub(結局使えなかったけれども)やfirebase realtime DBを使うことや、そもそも全体をkubernetesに載せて動かすなどできるようになったのは学生時代からの成長を感じます。

TODOの洗い出し

次に全体の設計に沿うように各コンポーネントでどんな開発が必要かをメンバーで議論しながら書き出していきます。

todo

初期のTODOリスト

上記のTODOはハッカソン中に書き込みが色々入った物ですが、ポイントはモジュールごとに分けてTODOを確認するということです。
上記で全体設計を行ったのがここでも生きてきますね。

その次に以下のように接続チェック(インテグレーションテスト)が必要な箇所を洗い出します。

インテグレーションテスト

今回はWebアプリケーションとして公開する必要があるので、ローカルでのチェックに加えてクラウド上での確認も必要でした。(上記ではdev/prodとしています)
作業を進めながらチェックをつけていき、全体でどのくらいが終わっているのかを見通し立てて進めることができます。

経験上、この段階で洗い出した初期のTODOはほぼ見積もり不可能です。

とはいえ、ここまでくればメンバー各々は自身がやるべきことが明確になるので臨戦体制となり開発に進みます。

開発スタート:1スプリント1時間の鬼回転

いつもは、ここから開発に入って適切なタイミング(1〜2時間くらい)で「そろそろ情報共有しよっか。」という感じで、情報共有+方向性の作戦会議のミーティングをとるのですが今回はスクラム開発の手法をチームに取り入れてみました。

スクラム開発では「スプリント」と呼ばれる2週間くらいの開発期間を元に「計画」、「振り返り」などのイベントを繰り返します。
今回のハッカソンではこれを1時間単位でやろうということになり、やってみることにしました。

スプリント1のスタートと終了時のMTG

開発の情報共有はslackを使っていたので、slackのリマインダー機能で1時間ごとに確認のMTGを促すように通知を送るようにしていざ開発スタートです。

1時間後にメンバー各々が開発をストップして情報共有をします。
だいたいTODOリストの残りに対しての進みがやばいということに気付きます。

引きづつき頑張るということで、また各々開発に戻っていきます。
ただし、スプリントの途中でも必要とあらばガンガンコミュニケーションを取ります

今回のハッカソンでは以下のような行動がそれぞれスクラムイベントと結びつきます。スクラムの概念についてはこちらをご参照ください。

  • スプリントレビュー:「どこまでできた?」
  • レトロスペクティブ:「このまま進めてできるかな?」
  • バックログリファインメント:「新しく生まれた作業とかある?」
  • スプリントプランニング:「次の1時間みんな何します?」

スプリント2〜3のスタートと終了時のMTG

このあたりで、当初の全体像が妥当かどうかが見えてきます。
今回は細かいところでは変更が必要そうではあっても

それぞれのタスクについて「どのくらいで終わりそうか」というあたりがつけられるようになるので、ここで初めてスケジュールを引き始めることができます。

この辺りで24時くらいまでに全部繋げようという感じになりました。
ちなみに、いつも24時までに繋げようといって繋がったことがありませんし、今回も予定通りには行きませんでしたね・・・。

スプリント4〜6

このあたりは、メンバー個々人のコーディングが乗ってきているので情報共有も最低限にしてせっせと作っていきます。

疲れたので、6スプリント終了あたりでカレー屋さんにいきました。
私は疲労しすぎて眠すぎて完全に寝てますね。みんな元気だな〜。

晩御飯を食べて眠くなった後は、また開発に戻ります。

スプリント7くらい〜

このあたりでもう一度TODOを整理したり、技術的に不可能っぽいことをやめて他の代替手段の検討をしたりしていきます。

当初のTODOを整理して、タイムスケジュールっぽいものなども作り始めます。

25:00〜30:00(2日目1:00〜6:00)

だいたいのハッカソンはこのあたりの時間で限界を迎える人ゾーンに入ってバリバリコード書く人に分かれます。
自分たちのチームはみんなバリバリコードを書いてました。

ここで最後のTODO整理を行い、以下のように「これが終わればとりあえずプロダクト完成」という項目と、「MUSTではないがやっておきたいこと」を明確にします。また、ポイントとしては何時までにできているべきかというのを明確にしておきます。

こうすることによって、頭ピヨピヨ状態でも「やるべきこと」をブラさずに開発をすることができます。
この辺りの時間はちょっと気を抜くと「あれ、何やるんだっけ?」となってしまいますね。

ハッカソン終盤の限界なやつ

ハッカソン終盤の限界なやつ

そして並行してプレゼン作りに励みます。

そして完成へ

12:00に作業終了となり、その頃には最低限動くアプリが完成しておりました。

完成したアプリがこちらです。(AIライバーオンナノコちゃん)

https://liveya.mocchiri.club/

システムの全体像がこちらです。(プレゼン資料より抜粋)

少しだけ利用している技術の解説をしておきます。

  • 全体のインフラ基盤GCP Kubernetes Engineで、全てのコンポーネントはDockerイメージとしてデプロイされています
  • トーク内容生成モデルについてはトーク内容の生成はYoutubeの配信者のスクリプトをクローリングしてきて、文章生成モデルを作成しています
    • 文章生成に当たってはランダムに数百の文章を生成した後にそれぞれの文をベクトル化し、頭の文から少しずつ距離を離すような並び順にすることによって「話題」のような単位を作成しています
    • この言語処理には文章の埋め込みやマルコフモデルなどを利用しています(LSTMは運用大変だからやめました)
  • トーク生成に関してはKubernetesのCronjobで上記の生成を逐次実行しデータストアをキューに見立ててデータを追加しています
  • Aggrigatorというシステムでキューに溜まっているトーク内容を適切なタイミングで音声生成できるように調整しています
  • 音声生成Open Jtalkを用いてチューニングした上で可愛くなるようにしています
  • フロントではそれらの音声をWebAudioを用いて波形レベルから口パクのロジックを作成してます
  • フロントNEXT.jsで構築されており、UIや可愛い動きが実現されています
  • ユーザーの入場やコメントはFirebase Realtime Databaseを通して即座に会話生成システムに送られます
  • 会話生成システムは基本的にルールベースの会話ロジックによりコメントに対する適切な応答を生成しDatastoreに次の発言としてキューイングします
  • それをAggrigatorがキャッチして・・・

という感じです。

自分で言うのも何ですが、ようできたな。。

 

このアプリの行く末

実はまだまだパワーアップさせようと画策しています。

今後は、複数部屋でみんなが好きな見た目と内容を話してくれるオリジナルライバー部屋を立てれて部屋にみんなを招待できるようにしていきたいと思っています。

そうして、その来場者数ランキングを一覧できるとかできたら楽しいかなと思ってます!
みんな遊んでくださると嬉しいです。

俺たちのハッカソンはまだまだ改善できる

さて、当日の振り返りが長くなってしまいましたが、ここからは今回のハッカソン全体を通して、学びや反省点などを振り返っていこうと思います。
(注:今回のハッカソンでは受賞ならずですw)

以下の内容は良いことであったり悪いことであったりを個人的な観点から振り返ってみたものです。

ハッカソンでは「プレゼン:プロダクト」 = 「5:5」

ハッカソンでは「実際に作ったプロダクトそのもの」と「プレゼン」が同じくらい、もしくはプレゼンの方が重要なくらいで評価されます。
実際のプロダクトも「マーケティング」などでうまくユーザーに届けられなければ意味がないので、同様かと思います。

今回はいつもプレゼンをやってくれているメンバーが別予定のためプレゼンできませんでした。
そのためいつもだったらそのメンバーががっつり取り組んでくれているプレゼンのブラッシュアップが少し後手に回ってしまっており、いつもよりプレゼンに力を入れることができていなかったように思います。

また、普段プレゼンを1人に任せてしまっていたため、チームの中でプレゼンに対するオーナーシップも少し薄れてしまったのかなと反省です。
プロダクトもプレゼンもみんなで同じくらい大事にアウトプット作れるようになるといいかもと思いました。

良くも悪くもメンバー全員プロトタイプの先が見えてしまっている

このメンバーではハッカソンで出したプロダクトをWebに公開するのが恒例となっていました。
たまに「そこそこ使われて運用が大変になる」という経験をメンバーが共有のコンテクストとして持っています。

そのため、あんまりめちゃくちゃなことするとアレかもという気持ちが少なからずあるのかなと思ってます。
ハッカソンでは技術的な挑戦や「こんなことする!?」というのをガンガンやって良い場所ですし、むしろそういうのもあってこそだと思っています。

普段、自分はデータサイエンスを活用した新しい技術や、ぶっ飛びなテクノロジーとかそういう物を無理やりプロダクションに載せるのですが、今回は少し安全方向に倒してしまったような気がします。

せっかく、インフラに強いエンジニアや色々よしなにしてくれるエンジニアやデザイナーがいるのですから、もっとぶっ飛んでも良かったのかもしれません。(あとが大変ですが)

筋トレすごい

今回はいつもハッカソンの途中で力尽きてしまうエンジニアが、筋トレをしていたために最後まで完走することができました。
終盤にマイナス1人にならずに、最後まで戦力落とさずにプログラミングできたのは完成まで持って行けた一つの要因だと思います。

また筋トレのおかげで自己効力感が上がっており、諦めずに実現できるまでバリバリ問題解決してくれたのもとても心強かったのでした。

プロマネ力↑↑

今回は私が本職の方でプロマネ力を少し鍛えていたこともあって、かなり効率よく進めることができたような気がします。

たまにハッカソンの終盤で「もう全然わからん。詰んだ。何すれば良いんだ。」みたいな事態がありますが、今回は割と「これが終わったら終わりや・・・やるしかない・・・」みたいなのが見えやすくなったのかなと思います。

そのため完成はいつも通りギリギリでしたが、いつもより少しだけ余裕はあったような気がします。

 

おわりに

とはいえ、今回も楽しくハックできました。
リリース後何人かの人に使ってもらえているのもとても嬉しいです。

運営してくださっているYahoo!の方々ありがとうございます!

今回も一緒に出てくれているチームメンバーに感謝!

@koooootake@dulltz@_kkimu@kurohune538

Pocket