🍣

ChatGPTを使ってライフプラン診断アプリを作ってみた

2024/07/15に公開

こんにちは、ryoooです

今回は、「ご家族のライフプランを診断いたします」みたいな保険屋さんにありがちなファイナンシャルプランナーのようなのをフロントアプリ込で作ってみたので紹介します

動機としては以下の2点です

  • 保険会社に務める友人がLLMでの接客可能性に興味をもっていたので試作してみたかった
  • Figma AIとかNotion AIなど自社プロダクトをLLMと結合する仕組みを実際に作ってみたかった(今回はライフプランのビジュアライズを行うフロントエンドのアプリを先に作って、それをChatGPTに操作させるような作りにしています)

完成品

早速ですが完成品はこんな感じです

gifファイルの3MB制限により見づらくなってしまっていますが、チャットウィンドウに家族の情報を入力していくとメインのペインにあるグラフがどんどん変化していきます

動作の流れを説明

  • 最初はチャットウィンドウだけ

  • 入力すると追加の情報をヒアリング

  • 詳細ビューではこんな感じでヒアリングした結果がシステムに入力されている

  • LLMによって自動入力された数値はすべて手動でも編集可能

作り

現在は以下のようにシンプルに作っています

  • 家族の状態はすべてFamilyContextに保持する
  • FamilyContextとバインドするように、グラフ描画機能を作る
  • FamilyContextを変更するコマンド(関数名 + 引数)を、LLMに生成させる
  • LLMには、現在のFamilyContextの状況も投げる

LLMが発行できるコマンド

コマンドとしては以下のようなものを発行できるように設定しています。
※ 金額はすべて「万円」を省略するように設定しています。

## createAdult
大人の家族を追加するときに使用してください。(システムに入力されているご家族の状況と照らし合わせて、大人を追加する必要がある場合のみこのコマンドを発行してください。)
\`\`\`json
{
  "command": "createAdult",
  "age": 40,
  "incomePerYearJpy": 400
}
\`\`\`

## createChild
子供の家族を追加するときに使用してください。(システムに入力されているご家族の状況と照らし合わせて、子供を追加する必要がある場合のみこのコマンドを発行してください。)
\`\`\`json
{
  "command": "createChild",
  "age": 8
}
\`\`\`

## setBankBalance
現在の銀行の預金額を設定してください。
\`\`\`json
{
  "command": "setBankBalance",
  "balanceJpy": 1000
}
\`\`\`

## setManagedAssetBalance
現在の銀行預金以外の運用資産残高を設定してください。
\`\`\`json
{
  "command": "setBankBalance",
  "balanceJpy": 1000
}
\`\`\`

## scheduledDeposit
退職金など将来の任意の時点で受け取る予定の金銭を設定してください。(このコマンドは積極的にユーザーにヒアリングせず、ユーザーから修正の要望があったときに使ってください)
\`\`\`json
{
  "command": "scheduledDeposit",
  "year": 2048,
  "balanceJpy": 2000
}
\`\`\`

## updateFamilyExpence
家族の生活費を修正する場合に、生活費の月額を設定してください。(このコマンドは積極的にユーザーにヒアリングせず、ユーザーから修正の要望があったときに使ってください)
\`\`\`json
{
  "command": "updateFamilyExpence",
  "balanceJpy": 20
}
\`\`\`

## updateFamilyPension
家族の年金を修正する場合に、家族の年金の月額を設定してください。(このコマンドは積極的にユーザーにヒアリングせず、ユーザーから修正の要望があったときに使ってください)
\`\`\`json
{
  "command": "updateFamilyPension",
  "balanceJpy": 20
}
\`\`\`

反省点

必要最低限の仕事だけをLLMにやらせるようにしたが、増分を考えさせたのは悪手だった

FamilyContextのパラメーターは多岐にわたりますが、今回、すべてをLLMに作らせることはしませんでした。

FamilyContextはPersonとAssetの配列であり、Personの操作可能なパラメーターとしては以下画像のようなものがあります。

たとえば、本当であれば職種や会社によって退職年齢や年収がピークを迎える年齢は変わるはずですが、今回はLLMには「現在の年齢と年収」のみをヒアリングさせています。
そのうえで、LLMが年齢と年収をシステムに入力したら、システム側で年収ピーク年齢と低減率などのパラメーターを生成してFamilyContextとして利用するようにしています。

構造としては以下のような形であり、LLMに作らせるのは基本的なパラメーターのみとしています。

これはLLMに複雑なことをさせるとどんどん精度が下がるための措置だったのですが、 状態の変化量をLLMに扱わせるのでなく、FamilyContextの型をLLMに渡して「描画すべきFamilyContext」を直接生成させるべきだったと感じています。

ユーザーは自然言語でやり取りをしているため、内部的に一部のパラメーターしかLLMが扱えないことは知らないはずです。そのため、システムが変数として扱っている要素はすべて自然言語で扱えるようにするべきだったと反省しています。

LLMの精度に対する対応は、質問分類器でプロンプトを切り替えるなど別の工夫をするべきだったと思います。

ちょうど以下のスライドが流れてきてそのとおりだと思ったのですが、私の試作の反省点は「LLMにモードを意識させてしまった」ということです。
https://speakerdeck.com/uenitty/why-declarative-ui-is-less-fragile

規模などにもよるのかもしれませんが、次に似たような仕組みを作るときはこのあたりをもう少し意識してモードレスな作りも試してみたい。

最後に

トークン埋め込みなのですが、記事公開後、しばらくのあいだは以下のサイトで動作するようにしておきます。
よろしければ触ってみてください
https://ryooo.github.io/lifeplan/

コードも以下で公開します
https://github.com/ryooo/lifeplan

最後までみてくださりありがとうございました :)

これからも個人制作や技術周りの情報をポストしますので、よろしければxアカウントryoooをフォローいただけると嬉しいです

Discussion