LLM活用方法の模索日記その1
こんにちは。株式会社フィノバレーでモバイルアプリチームのリーダーを担当している照井です。
今回は去年(2023年)に試したLLMの模索と検証内容の第一弾を紹介したいと思います。
1年以上経ってしまっているので情報がかなり古いですが、こんなことも考えているんだなと伝われば嬉しいなと思い今更ですが書いてみました。
はじめに
2023年はChatGPTを筆頭に様々なLLM(大規模言語モデル)が登場し、個人で手軽に利用できる時代になったのはとても衝撃でした。多くの企業や行政でLLMの導入が進んでいるようなニュースが飛び交う中で、私も自社でLLMを使って何かできないか模索していました。
よくあるアイディアとしてはChatbotやRAGだと思います。RAGは今でこそDifyやFirestoreのベクトルDB対応など色々出てきたものの、検討を始めた2023年6月あたりではまだRAGを構築するのが面倒&コストがかかるものであったため、費用対効果が見込めるのか懐疑的で悩んでいました。
メイン業務の傍で検討を進めるということもあって、あまりコストをかけずにMoneyEasyにとってそこそこ有益になりそうな使い道を模索していました。模索する中で目をつけたのが翻訳です。MoneyEasyでは多言語対応の需要はあるものの対応工数が非常にかかることがわかっていました。そこで現サーバーロジックとは別に稼働する"簡易で高速な翻訳API"がLLMをベースに作れるのではないかと考えました。
はじめに書いてしまいますが、最終的にLLMを活用する結果にはなりませんでした。その理由と経緯も記載します。
検証環境の構成
検証時に利用した技術・サービスとその構成は以下の通りです。
翻訳API機能
Firebase Cloud Functions
Firestore
Node.js + TypeScript
検証用のUI
Firebase Hosting
Flutter web
選定基準
プロダクトで使用するか未定ではあったものの、一応本稼働を想定しつつ私が慣れている技術を利用することにしました。
Cloud FunctionsはCold Startでインスタンス起動に数秒かかってしまう関係で、本番運用する場合は工夫が必要となります。ただ、検証用としては十分で他のFirebaseサービス(FirestoreやFirebase Hosting)との親和性も高いため採用しました。
翻訳APIを検証するため、言語選択リストや日本語入力フィールド、結果表示とそのレスポンスタイムなどを表示するためのUIをFlutter Webで作成しFirebase Hostingにデプロイして検証しました。このUIの話は本記事の内容とずれてしまうので触れません。
翻訳API作成時の工夫点
一度翻訳した文字列はキャッシュし、次回以降、同一文字列はいちいち翻訳せずキャッシュから取得するようにしました。
弊社MoneyEasyのサービスの特性として、翻訳対象の文字列の中で可変に変更される文字列というのはほぼありません。加盟店様の情報はそれなりに更新される可能性がありますが、例えば1分に1回などリアルタイムで更新されるようなものではありません。そのため、比較的同じ文字列を翻訳するという処理になります。
今回の検証で気にするところは主に性能とコストなので、可能な限り他サービスAPIの実行回数を抑えるように考えました。
具体的にはFirestoreを使用し翻訳文字列をハッシュ化してキー検索、キーがあれば翻訳済みの文字列を取得し、キーがなければ保存するという仕組みにしました。
本番運用する場合はバックエンドのどこかでこの機構を実装することになる可能性もありますが、とりあえず検証段階では作成する翻訳APIに内包してしまおうと考えました。
キャッシュにすることでもう一つ利点があり、翻訳した文字を保存せず毎回翻訳にかける、という設計に仮にした場合(あまりないかもしれませんが・・)同じ文字列に対して微妙に異なるニュアンスの訳が生成されるのは品質的にもあまり良くありません。キャッシュしておくのであればこの問題は解消されるかなと思います。
GPT-3.5 APIの検証
検証に利用したモデルはOpenAI社が提供するgpt3.5-turbo-0613です(2023年6月当時の話です)。当時はgpt3.5-turbo APIが安価で精度の高い翻訳が可能であることがわかったため、このモデルを使用してサンプルコードを書いて検証しました。
ただ、大きな問題が一つありました。当時SNSでも話題になっていましたがgpt3.5-turbo APIの出力が安定しないという問題です。
翻訳は問題なく行われるものの、前後に「Translation: ------」などと区切り線をつけたり、冒頭に「翻訳しました」などの文字が追加されるケースがありました。プロンプトを工夫したものの100%消去し翻訳文字列だけ出力することは難しそうでした。
当時Function Callingも出始めていたので、もしかしたらそちらを使用して出力を安定させられた可能性もありますが、精度に問題があったような投稿がSNSにあった記憶があります。後々に登場したJSON modeでも指定の形式で返してくれるのではと思いましたが100%の精度ではないと報告されています。
(JSON modeは2024年8月6日にOpenAIから「AIにデータを構造化させる際に、指定したスキーマに確実に従わせることが可能なモード」というものが出たようでJson形式としては100%の精度で返してくれるそうです。)
翻訳サービスの整理
そもそも検証を始めた経緯が「LLMの活用」を前提としていたため思考順序がおかしなことになっていますが、本来はまず最初にこのフェーズが入ると思います。一旦立ち戻って考え直し、LLMの活用は置いておいて「最もプロジェクトにとって有用に翻訳APIを実現できる方法は何か?」をGPT-4と相談しました。
その結果、翻訳APIとしてGoogle Translation APIを薦められました。Google Translation APIはコストがかかると勝手に思い込んでいましたが、料金もさほどかからないことが判明したため、これも視野に入れて性能と精度の検証をすることにしました。
性能検証
いくつかのサンプル文字列をgpt-3.5-turbo、Google Translation API、DeepLで日本語→英語の翻訳をし、GPT-4でそれぞれの翻訳精度を評価しました。評価点と料金をまとめて記載します。(サンプル数は非常に少なく、数回実行した平均値なので誤差はかなりあると思いますがご了承ください。)
gpt-3.5-turbo API
精度: 95点 (非常によく適切に翻訳されている)
300文字程度の文章のレスポンス: 3〜5秒
料金: 1000token / $0.002(2023年6月当時)
Google Translation API
精度: 90点(4つ指摘あり)
300文字程度の文章のレスポンス: 0.5秒
料金: 初回50万文字無料。その後、100万文字あたり$20(1000文字あたり$0.02)
DeepL(これはAPIではなくブラウザで実施しました)
精度: 85点(4つ指摘あり)
300文字程度の文章のレスポンス: ー (ブラウザのため未測定)
APIの料金: 基本料$5 + 1000文字 / $0.02
検証当時はgpt-3.5-turboが一番高い精度となる結果でした。ただしこの結果にはいくつかの要因が考えられます。
例えば、翻訳対象としたサンプル文字列は実際にMoneyEasyサービスで使用している文字列をピックアップしたのですが、この文字列には当然専門用語はほとんど含まれていません。
DeepLは技術文書や学術論文などで高い翻訳評価を受けている認識ですので、翻訳対象分野で評価は変動するはずです。
この時点でgpt-3.5-turboとGoogle Translation APIを比較しました。1トークン1文字としてもGPT-3.5の方が安価ですがGoogle Translation APIも毎月$10分の無料クレジットがありますし十分な翻訳の精度がありました。レスポンスが早いところも高評価であったため、最終的に翻訳APIはGoogle Translation APIを使用して実装する方法が最も望ましい、という結論になりました。
まとめ
当初目的は「LLMを使って何かできないか模索する」だったので、Google Translation APIを使うという結論になってしまったのは少し残念でした。
ただ、そもそもLLMを使うこと自体が重要ではなくプロダクトのニーズに合った技術を選ぶことが重要ですので、今回の検証は良い成果が得られたと考えています。
2024年8月現在ではGPT-4o miniやGemini 1.5 Flashなどもっと安価に使えるAPIが提供されてきたため、今試すならこれらのモデルになると思います。
今ならGoogle Colaboratory+ローカルLLMを使うという選択肢も検討の余地があるのかなと思います。ただ、Colabのコストを考えると翻訳APIの実行頻度と要相談という感じになりそうです。
今回の検討日記は以上で終了です。2023年後半や今年の前半でも、少しですがLLMの模索&検証をしてきましたので日記その2や日記その3で書いていきたいと思います。