【都知事杯オープンデータ・ハッカソン2024】 4 . TypeScriptとHonoを使用したバックエンド開発
こんにちは。C-Styleで主にバックエンド業務や社内改善業務を行っている、しゆいです。
私を含めた C-Style のエンジニアが「都知事杯オープンデータ・ハッカソン2024」にバックエンド担当として参加しました。私は主にバックエンドを担当したので、そのレポートをさせていだたきます。
まずは今回のハッカソン体験談 [ 1 .概要とサービス紹介 ] を読んでいただくと私のレポートがわかりやすくなると思います!
つくったもの
今回作った ”WonderNest /wʌ'ndər nést/” は、主にお子さまがいる方に向けたプロダクトです。プロダクトの詳細についてはこちらの記事をご覧ください。
メンバー
元々、バックエンドは 2 人での開発を予定していたのですが、事情があり私 1 人で実装しました。詳しくは こちらのPM が執筆した記事をご覧ください。また、デプロイ等を諸々担当しました。
使用技術・概要
今回は元相方の要望によりTypeScript、そして最近HOTなWeb application frameworkとしてHonoを採用しました。プロトタイプということもあり、NestJSほどの重さは必要なく、開発期間も短いため、Fast, lightweight, built on Web Standards. Support for any JavaScript runtime. をうたっているHonoが良いのでは、そして単純に最近HOTな技術を触ってみたいという考えから採用しました。
link: https://hono.dev/
今回のアイデアをもとに、メンバーで使用する技術を模索していたところ、OpenAIのAssistant、そしてデータを食わせてベクトル化させておくことができるVector Storeがよさそうだという話になり、今回はOpenAIをフルに活用した実装となりました。The official Node.js / Typescript libraryであるopenai-nodeを用いました。
Requestの際、毎回毎回特定のファイルをAttachしてAssistantに処理させるのは処理速度的にも処理内容的にもあまり嬉しくありません。しかし、事前にVector Storeに用いたいデータを食わせておけば、Assistantを呼び出すときはVector Storeに一意に割り振られているVector Store IDを指定してあげるだけで、事前にVectorとなっているデータを参照するだけで済みます。
今回OpenAIを用いた主な理由としては主に 2 点あり、
1 点目は今回用いたオープンデータの表記が統一されておらず、従来存在するような愚直な検索よりも、AIを用いた曖昧な検索の方が、ユーザの求めている情報を適切に返却できると考えたからです。
2 点目は、OpenAIのPlaygroundを用いて動作確認を行った際、想定よりも非常に安い料金での処理が可能であるとわかり、token数を改善することでよりコストを下げることができることが見込めたためです。
link: https://platform.openai.com/docs/overview
ーーーエンドポイントについて
今回はハッカソンという短い開発期間ということもあり、必要最低限のエンドポイントを二つ実装しました。OpenAIを用いている都合上、APIにはCloudflare側で認証をかけて余計なRequestを受け付けないようにしています。
以下の二つのエンドポイントを実装しました。
フロントからのリクエストに応じて、LLM を用いて検索するエンドポイント
ユーザからもらったデータを検索対象に追加するエンドポイント
Search API では、フロントから送られてきたqueryをAssitantが喜ぶ形式に変換してリクエストを送信しています。ドキュメントが存在しないので、気になる方は公式の実装を見に行ってみて下さい。
https://github.com/openai/openai-node/blob/master/src/resources/beta/threads/threads.ts
今回グレーなハックをした、データ追加エンドポイントの話をします。まず前提として、今回用いたオープンデータの大半はCSV形式で都から提供されています。しかし、OpenAI Vector Store ではCSV形式のファイルをサポートしていません。ファイル形式を.txtにしたりtext/plainとして作成したとしても、中身はCSVなので OpenAI君には「お前これCSVやないか」と見抜かれてしまいます。そこで、二つの対応を行うことでtxtに錯覚させました。
まず、CSVの 1 行目にはヘッダがあります。その前の行に、伝家の宝刀
# Ignore this line / この行は無視してください
という文字列を追加します。こうすることで、OpenAI君は一行目を見てCSVのヘッダがないな、、じゃあtxtだな!と理解してくれます。
これだけではありません。OpenAI の Assistant には、 Instructionsというものが存在します。 Instructionsというのは簡潔に言うと、Assistant にどのように振る舞って欲しいのかを定義するものです。
そこに、またまた伝家の宝刀
They are CSV, but please ignore any lines in the file that start with #.
という文章を追加します。
こうすることで、先ほど 1 行目に追加した# Ignore this line / この行は無視してください をAssistantは無視してくれ、Assistant君は良いようにCSVとして解釈してくれます。最高ですね!
ーーーデプロイ
デプロイに関してはフロント、バックともにCloudflare (Pages , Workers)にそれぞれデプロイしました。
link: https://pages.cloudflare.com/ https://workers.cloudflare.com/
私は上記すべての技術の経験がなかったのでキャッチアップしながらの実装でしたが、結果としては当初想定していた仕様+αのエンドポイントまでの実装を二日で完成させることができ、満足のいく結果となりました。
困難だったポイント
困難だったポイントとして、実装に公式ドキュメントが追随できていないというのがありました。
ドキュメントには 1 文字も出てこない関数が多数存在し、実働時間の半分以上は、実装を追っていました。ライブラリへの関数等の追加がdays agoだったりweeks agoだったりと更新が多く、追随できていないようです。
実装を追うのにはVSCodeを活用し、ひたすら使えそうな便利な実装がないかを読んでいました。楽しかったです。
終わりに
初めて、オフィスに出勤して人と会話しながらの労働。初めて触ってみる使ってみる技術。全てが新鮮で楽しかったです。ハッカソン開発期間初日はかなり不安の占める割合が大きかったですが、開発を終えてみて、自分のキャッチアップ力、実際の実装を読み解いてそれを使って書き起こす力の上達を感じました。そして、美しいJSONがログに出力される感動は、バックエンドを書いている人なら共感できる部分があるのではないかと思います。
非常に貴重な経験ができました。お読みいただきありがとうございました。
ハッカソン体験の技術的な詳細や工夫、エンジニアやマネージャーからの直接の感想にご興味がある方は、ぜひこちらの記事をご覧ください!今回は、それぞれの個性を活かして執筆をお願いしたため、現場のリアルな声をお届けする内容となっています。
この記事が気に入ったらサポートをしてみませんか?