社会人になってから初のhackathonに参加した

社会人になってから初のハッカソンに参加してきたので、備忘録として本投稿を行う。

ハッカソンとは、主にソフトウェア開発におけるエンジニアやデザイナー、プログラマーなどが集まり、一定期間集中的にアプリケーションやシステムなどを開発するイベントのことです(Wikipedia参照)。

今回は「エンジニアType」さんが主催の「 ChatGPTサービス開発ハッカソン」に参加しました。

type.jp

ハッカソンのテーマと評価軸

今回のハッカソンのテーマは、名前からわかるように「ChatGPT」を使用したサービスの開発です。

なので、最低限の条件としてマストなことは成果物に「ChatGPT」が組み込まれていること

あとは、審査員による評価軸として「イノベーション性」「事業としての成長可能性」「完成度」でした。(ハッカソンというよりアイデアソンの評価軸っぽい評価軸な気がする)

参加したモチベーション

これまで学生時代に何度かハッカソンに参加してきましたが、ここ1年半ほどは就職活動や新卒研修で忙しく、こういったイベントはご無沙汰でした。

最近ようやく環境の変化が落ち着き、「仕事とは関係のなく、短期間でゴリゴリアイデアを開発して作りたいな」という気持ちがあり、イベントを探していたところにちょうどイベントの情報が流れてきたので参加しました。

元々大学の同期6人で活動しているコミュニティがあり、現在3人が学生、3人が社会人という感じなので、社会人メンバーに声をかけて3人チームでエントリーしました。

実際に作ったもの

最終的に開発したものは、プレゼンテーション資料(いわゆるスライド)を自動生成するシステムです。

簡単にシステムの画像と共に説明していきます。

トップ画面

システムは簡単なWebアプリケーションとして開発していて、サイトを開くとまずこのトップ画面が表示されます。開発期間が圧倒的に足りないので、画面はカスみたいなデザインになっています。 ハッカソンあるあるですね。「最低限動く」ということを目標にMVPを実装していきました。

画面に表示されている「Generate New」というボタンをクリックするとスライドの生成ができます。

ホーム画面

スライド生成画面

トップ画面から写真の画面に遷移します。

この画面では、プレゼンテーション資料を作成するにあたって必要な情報を入力します。

入力する情報は以下のようになっています。

  • プレゼンテーション資料のタイトル
  • 原稿
  • 発表背景
  • 想定発表時間
  • 生成するスライドのフォントサイズ

[補足]

原稿:そのままの通り、プレゼンテーションの原稿です。とは言っても、しっかり原稿を考えろというわけではありません。基本的にプレゼンテーションを作成するときになって、「どんなことを話そうか」と考える人は少ないと思っています。ある程度頭の中に「話の流れや構成」、「どんなふうに説明しようかな」といったことはでき上がっていると私は考えており、それを入力してもらう欄になります。

発表背景:プレゼンテーションの内容に直接的に完成はしませんが、「どんな経緯で発表するのか」「どんなオーディエンスが想定されるのか」「どんな内容を重点的に伝えたいのか」などを入力します。

最後に「Generate」をクリック。

そうすると再びトップページに飛ばされます。

写真にあるように「generatied now...」という表示が増えていますね。

(個人的に「generatied now...」という表現には違和感がすごい... せめて「generating now...」)

これが先ほどのスライドが生成中である(生成が始まっている)ことを意味しています。

しばらく時間を置いてから再びサイトを覗くと、生成が完了している場合は「generatied now...」という文字がきえ、先ほど入力したタイトルが表示されるようになっています。

このタイトル部分(カード)をクリックすると生成したスライドを確認が可能です。

生成したスライドの確認

生成されたスライドのタイトル部分(カード)をクリックすると先ほどの生成画面と同じような画面に遷移します。

しかし、よくよく見ると「スライドURL」というものが追加されています。 これが生成されたスライドを確認できるURLになっています。

実際にURLに飛んでみると、こんな感じで生成されたスライドが確認できます。

以上が、今回開発したシステムです。

開発者的なつらみ

↑がシステムの全体的な構成です。

まぁ無難な感じですね。

ユーザーが操作するアプリケーションをWebで提供し、そのリクエストをREST APIで受け取り、DBに記録します。

スライドの生成には時間を要することが考えられたので、非同期的に生成リクエストのチェックを行い、それに伴ったスライドの生成を行うWorkerを立てていました。 Workerは、「GPTとのやりとりを行うもの」、「GPTのアウトプットをParseして、Google Slide APIを使用して自動でスライドに配置するもの」の2つを立てていました。

1つのWorkerでやってもよかったんですが、途中で処理が失敗した際のreloadのコストを考えると別プロセスとして独立させるべきだなと判断し行いました。(そもそもスライドの生成に時間がかかるのでタイムアウトになりそう。)

あとは、非同期的にタスクを実行する際にWorkerの起動の起点としては、メッセージングシステム(今回はRabbitMQ)の使用を考えていたんですが結局実装時間的にDBを仲介点としてそのまま使用しました。

つらみ1

今回、ChatGPTの使用がマストというところで、そもそもシステムにどう組み込むのかという点で悩みました。

最近出ているChatGPTを使用したサービスは、以下の2種類の大体が収まると思っています。

  • その会社で蓄えてきた事業ドメインの知識を食わせることで自動応答Botとして価値を持たせるもの
  • ChatGPTのインターフェースを音声、アバターなどを組み合わせてカスタマイズすることで価値を持たせるもの

超個人的な意見ですが、どちらのシステムにもあまり価値を感じていません。素のGPTを使い慣れている自分からするとGPTでいいじゃんとなってしまいます。(前者のドメイン知識を活用したBotには多少価値はあるなと思います。) ましてや短期間で、しっかりとシステムとして価値あるものを作れるイメージがわかりませんでした。

どうしても「それって、GPTじゃダメなの?」で玉砕されそうでした。

頭を捻りまくった結果として今回いけると思ったのが、スライド生成でした。

GPTに以下のような形式のプロンプトを渡しました。

クラス名: ClassName

インプットプロパティ:
- property1:propertyの説明
- property2:propertyの説明
- property3:propertyの説明

アウトプットプロパティ:
- property4:propertyの説明
- property5:propertyの説明
- property6:propertyの説明

メソッド:
    method1():~~~~~なメソッド
   method2():~~~~~なメソッド

    method1()メソッドの手順:
        説明

    method2()メソッドの手順:
        説明

このように、ClassNameクラスは、入力として~~~~~を受け取り、~~~~する抽象クラスです。具体的な実装や具体的な自然言語の処理方法は省略されていますが、この抽象クラスを実際のプログラミング言語で具体化することで、具体的な動作や出力を得ることができます。

さて、あなたはClassNameクラスです。インプットプロパティを渡すので、余計な言葉は省いてアウトプットプロパティだけ出力してください。

まずユーザーがメッセージを送るので、それをインプットプロパティに渡して、ClassNameの結果を返してください。

これによって、GPTがユーザーが入力したプレゼンテーション背景などを加味した上で、発表時間に適切な枚数のスライド分のサブタイトルと記載する内容、発表時のスピーカーノートを生成してくれるようになります。

このような曖昧な自然言語を解釈し、目的のアウトプットを出してもらう。そしてそれをプラスαでスライドとして加工してユーザーに提供するという点にシステム的な面白さとGPTを組み込む価値を見出すことができました。

つらみ2

今回作成したGPTのプロンプトは、gpt4を使用して作成していました。そのプロンプトをもとにOpenAIのAPIを使用しようと試みたところ問題が起こりました。

APIでまだgpt4が提供されてねぇ...」

正しくは、事前にwish listに登録している必要がありました。間違いなくハッカソン機関には間に合わなそうです。試しにgot3.5で実験したんですがプロンプトを解釈することもできませんでした。

どうしようかと頭を捻らせたんですが、最後の手段として chrome extensionを作成してブラウザを自動操作することで、ブラウザ経由でgpt4を利用することに決めました。

僕が、ChatGPT Plusに登録していたのでブラウザ経由からはgpt4を使用可能でした。ChatGPTのHTMLを確認し、プロンプトの入力を行うテキストエリア、送信するボタン、生成結果の表示される要素それぞれのClassNameやidを特定し、持っているvalueの監視、valueの入力、eventの発火をしました。

これによって、プロンプトを入力し、送信、結果を生成待ちして生成が終わったタイミングでdbに送信する。

ということを自動でできるようになりました。本当につらみでした(本来想定していた工数から大きく乖離)。

つらみ3

最後のつらみは、Webフロントでした。

今回は、TyprScript・React・Ant Designといった構成でフロントは作成しました。 今回のチームメンバー全員がメインで触っている技術はWebではないので、簡単なWebアプリケーション1つ作るのも大変でした。

例の如く状態管理が大変だった、、、、

あとは、デザイン力が乏しいなと思いました。とはいえ、デザインを凝ったとしてもハッカソンの短い開発期間で実装できるかと言われると怪しい、、、

ハッカソンは結局目に見える部分が結果を大きく左右すると思うので、今回僕たちのチームは裏側の処理は頑張ったんですがフロントは結構やっつけだったので、「うーん」という感じでした。

Webももっと強くなりたい。(それかいい感じのUIをぱっと作れるiOSや他プラットフォーム上のBotとして作ってもよかったのかもしれない。工数的にも)

まとめ

色々困難や反省はありつつも結果的に動くものを作り上げることができたのでよかったです。

ハッカソンに参加したモチベーションである「仕事とは関係のなく、短期間でゴリゴリアイデアを開発」という意味では十分達成できたと思っています。

他チームの発表を見て、まだまだ触ったことのない技術(音声認識VRアバター)を組み合わせているチームがあり刺激をもらえたこともよかったです。

自分はどうしても技術者として自分の扱える技術からアイデアをひねりがちなので、そういった意味でも思考が広がったと思います。

また今回スライドを作成するにあたって使用したGoogle Slide APIなどは初めて触ったので、学びでした。 社会人になってから初のハッカソンでしたが、本業で身につけた知識が生きる場面もあり成長を実感できたことも学びです。

次は10月のハッカソンの参加が決まっているので、それまでにもっと強くなっておきたいと思います。