💥

記事要約サービス今北産業をリリースしました!

2024/08/10に公開

ぜひまずは1度触ってみてください!!

https://3lines.me/

今北産業

有名ネットミームですよね。
ネットミームを解説する事ほど野暮なことはないので、意味を知らない人は自分で調べてもらえると、、

今北産業は技術記事のURLを貼るだけで3行に要約してくれて簡単にシェアハピできるサービスです。

裏ではGeminiのAPIを叩いて、3行の要約を取得しています。
要約を取得して、気に入ったら登録しましょう。気に入らない場合は要約を直接編集することもできます。

登録すると詳細画面が作成されます。詳細画面のURLはOGP画像が設定されているのでXへのPostボタンからPostすることでシェアした時にタイムラインで目に止まりやすくなります。

技術構成

シンプルなサービスなので、これ以上書くことないのですが、技術構成について少し触れようと思います。

  • フロントエンド
    Next.js + TypeScriptで開発したものをVercelにデプロイしています。
  • バックエンド
    Firebaseを利用しています。GeminiのAPIはFirebase Functions経由で呼び出しています。
    Functionsは2ndGenを利用して画像の扱いがしやすそうな気がしたので、pythonで書いています。
    • Firestore (Summaryの保存)
    • Fucntions (GeminiAPIの呼び出し、画像の生成、画像やSummaryの保存)
    • Storage (画像の保存)
    • Authentication (匿名認証、GitHub認証)

Geminiを使って要約をする処理

Geminiはフロントから直接叩くわけにはいかないので、FunctionsのOnCall経由で呼び出しています。
Functionsを叩く際にURLを渡してあげて、BeautifulSoupを利用して、記事の中身を取得、Geminiに丸投げしています。
GeminiにはJson形式フォーマットでレスポンスを返すように指定していて、Functionsでレスポンスを受け取ったら、正規表現を利用して、フォーマットに合っているかをチェックして、フロントに渡しています。

要約から画像を作成して、保存する処理

こちらも同様にFunctionsのOnCallトリガーで呼び出しています。
元々用意してあるバックグラウンド用の画像にpillowライブラリを利用して、要約を配置しています。
画像を生成したら、そのままCloudStorageに保存しています。また、Firestoreにも要約の内容や画像のURL、元の記事のURLなどを保存しています。
あと現状は使ってないですが、元記事のドメインもこの時点で切り出して保存しています。ゆくゆくはドメインごとにどの媒体で書かれた記事なのかわかるようにできたら良さそうと思ってたりします。

動的OGPの生成

要約ごとの詳細ページがあるので詳細ページはSSGを利用して動的にOGPを設定しています。ここで画像や記事のタイトルを事前にHTMLに埋め込んでおくことで、SNSなどでOGP画像が展開されるというメリットを実現しつつ、SSGで事前に用意しているので、レスポンスが早くなったり、Firestoreへのアクセス回数も減っているかなと思います。

苦労した点、うまくできていない点

Geminiがいうこと聞いてくれない

3行で要約して画像に当てはめるためにそれぞれの文字数が全角で30文字以内というルールにすることにしました。そのため、Geminiへのプロンプトではそれぞれ30文字以内で返してくださいと伝えているのですが、普通に40文字とかで返してきます。
いろいろ調べたのですが、文字数を厳密に指定する方法が調べきれなかったので、長すぎるレスポンスの場合でもその後ユーザが編集できるようにしてエラーにはならないようにしています。

文字数制限で扱うの微妙

1つ目にも関わる話なのですが、生成する画像の文字サイズは固定、改行はしないようにしたいと思っており、そのためには要約として登録した文字が改行しない最大の文字数で制限をかけたいのですが、半角が混ざると同じ横幅に入る文字数が変わってきてしまいます。
その文字数は(おそらく)描画後にしか取得できないので、バックエンドで画像を生成している以上正確に上限の文字数を扱えないです。仕方ないので、現状は全ての文字が全角だった場合に改行しない最大の文字数の30文字を制限にしています。
30文字ってかなり少ない(特に英単語が含まれると一気に文字数を使う)ので、改行しない最大の文字数を取得する方法があれば教えていただきたいです。

プレビュー画面と詳細画面のUI

プレビュー画面と詳細画面には生成された画像とほぼ同じ見た目の要約が表示されています。一覧に表示されているのは生成された画像をそのまま表示しているのですが、プレビュー画面と詳細画面はNext.jsで同じような見た目になるように書いています。
画像の場合は画像のサイズに合わせて全体の大きさが一律で変化するので、文字のみかけのサイズも変化しますが、一般にフロントで書かれた文字サイズは全体のサイズに関わらず一定なので、画面サイズに関わらず画像と同じ見た目にするのが難しかったです。

最終的にはSVGコンポーネントを利用することで、画像と同じように拡大縮小が反映されるようになりました。

おわりに

今北産業は Gemini API Developer Competition に提出しようと考えています!
8/26~9/30に一般投票もできるようなので、ぜひ今北産業面白いなと思ってくれた方は投票してくれると嬉しいです!!(今すぐ投票できないのが悔やまれる。。)

2024年は技術発信も頑張ろうと思っているので、記事が参考になった方は記事とGitHubのいいね(スター)とフォローをしていただけると励みになります!
最後まで読んでいただきありがとうございました✨

https://github.com/miyasic/3lines

Discussion