ローカルLLMを用いたポートフォリオ生成アプリを作ってみた
はじめに
どんな人向けの記事?
- 生成 AI に興味がある方
- ローカル LLM に興味がある方
- 資産運用に興味がある方
Mac Studio(M2 Ultra 128GB) + Claude MCP (filesystem + git)
概要
現在、ちょっとした Web アプリを作っていて、その中間成果物としてローカル LLM を用いたポートフォリオ生成アプリを作りました。
今回は、そのアプリの簡単な紹介と開発の中で得られた知見等を備忘録的にまとめます。
「ちょっとしたアプリ」に関しては完成してからのお楽しみということで、今回はポートフォリオ生成アプリの開発までに焦点を当てた記事となっています。
アプリの紹介
ポートフォリオ生成アプリについて語る前に、Claude MCP を使って作った LLM キャラ管理アプリを簡単に紹介します。
このアプリも中間成果物の一つですが、基本的にやっているのは下記の通りで非常に単純なシステムです。
キャラクターの設定を入力するだけで LLM が推論したステータスを可視化できるので、これだけでもまあまあ面白いです。
今回はさらに、作成したキャラクターの情報から資産ポートフォリオを作成する部分を実装しました。現状のアプリ画面はこちらです。
まあ今回実装した部分も補完と可視化だけなので、やっていることはLLMキャラ管理アプリと変わりないのですが、開発過程で色々と苦労した点や学んだことがありました。以下ではそれらについて述べます。
開発で苦労した点
さて、ここからは主に開発で苦労した点などを中心に記載します。
開発環境
まず、開発環境は Mac 上の Claude デスクトップで、Claude MCP + filesystem + git でほとんど作りました。理由は単純で、API 料金を極力払わずに Claude の力を使って半自動的に開発を進めたかったためです。
以下の記事でも述べましたが、Claude MCPは正直Clineに比べると及ばない点が多いです。
おまけに、最近のバージョンアップやRoo-Clineというフォークを使うことで、さらに自由度や完成度が向上しています。一方で、Claude デスクトップは特に進化している感じはないです。
それでもなお、Claude MCPにこだわる理由は20ドルのサブスク代だけでかなりClaudeを使い倒せる点にあります。
苦労した点と解決策
以下では、Claude MCPを通じた開発の苦労した点と自分なりの解決策などをまとめています。
苦労した点 | 解決策 |
---|---|
Claudeのサボり癖 (コード省略) |
プロンプトで対処(多少サボりにくくなる) 「コードを省略することは万死に値する」 「絶対にコードを省略せず、完全なコードを出力してください」 「既存の機能を絶対に喪失しないように注意しながら、依存関係がわかるように丁寧にファイルを分割して」 |
レートリミット |
定期的にREADME.mdを更新 ProjectのKnowledgeで管理し、できるだけ新しい会話から始めることでトークン数を節約 |
破壊的変更(まれにある) | gitで対処 |
LLM関連などごく最近の機能取り込み | 仕様やサンプルコードをプロンプトに入れる |
失敗談
破壊的変更
開発の途中でキャラクター管理画面が大幅に変わってしまったことがありました。
まあこれはこれで悪くはないのですが、個人的にはレーダーチャートの方が好みなので却下しました。しかし、Claude MCPでは一度加えた変更を元に戻すのは結構難しかったりします。その理由は下記の通りです。
-
ClaudeデスクトップではESLintエラーに対処できず、デバッグ作業が煩雑になる。
- 正確にはエラーメッセージを渡せば対処できるが、大規模な改修があったときには大量のESLintエラーに起因するデバッグ作業が発生する。
- 一方、ClineではVS codeやCursorを使っている恩恵か、エラーメッセージを渡さなくてもESLintエラーに気づいて修正してくれる。
-
色々デバッグした後に「その部分だけ元に戻して」、と伝えても中途半端なところまでしか戻れず、結局そのブランチは放棄することにした。
細かい全体仕様を渡して一気に作るか、ステップバイステップで作るか問題
私は最初、細部まで記載した全体仕様を渡して一気に作るということにトライしました。
すると、Claudeはひたすらファイルを生成し始めます。
どんどん新しいファイルができていく!これは素晴らしい!と最初は思っていたのですが、一通りのファイルが出来てから始まるのが長い長いデバッグ作業。
メイドインアビスの概念で例えるなら、「ファイルがたくさん生成される」=「アビスの階層が深くなる」、「デバッグ作業」=「上昇負荷」という感じでしょうか。デバッグが完了して、フロントエンドの起動に成功するまでアウトプットが見えないのが恐ろしいところです。
ゼロから作るときはまだいいかもしれませんが、中途半端なプロジェクトからこれをやると上昇負荷で原型を留めないコードベースが出来上がります。
その結果出来上がったのがこの画面です。
一見、ワクワクさせられるような素晴らしいページですが、実のところ出来ているのは見た目だけで中身は何一つ出来ていません。そして上記の破壊的変更に加え、仕様に書いていなかったスキルなどの謎の項目。
いやまあ確かに、これ全部実装できたらかなり面白いものが作れるとは思いますが、自分が作りたかったものからはかけ離れています。これがモックアップではなく、自分の想像を超えるアプリが動く形で生成されていたら良かったのですが。。。
仮にこれを実装するとなったら、具体的な仕様を追加で検討する必要があり、さらにこの10倍以上のデバッグ作業が必要になりそうです。色々と考えた挙句、このブランチで開発を続けるのは断念しました。
ということで、その後はステップバイステップで少しずつ機能を追加していく方針に変更しました。少なくとも今の私のレベルではこれが最適だという認識です。
その他気づき
-
pydantic_aiはTools対応モデルしか使えない
- 最初、投資方針や根拠、ポートフォリオ生成にpydantic_aiを勉強がてら使っていたのですが、Toolsが使える一部モデルにしか対応していないことに気づきました。
- というわけで、モデルの依存性がないOllamaのstructured outputを利用することにしました。
-
バックエンド開発では、できるだけ自分がある程度読み書きできる言語を使うべき
- プログラミング言語の勉強をしたいとか、Vercelなどでデプロイしたいなら別だが、単にアプリを作りたいだけの場合は自分である程度読み書きできる言語を利用したほうが良いです。
- 全部Claude任せにすると、Claudeが対処できなくなったときやClaudeが使えない時間帯に作業が滞ってしまうため。
-
Claudeと認識合わせをしてから作業を進めるべき(仕様どおりに行かない場合は特に)
- 例えば、UIやデザインで気に入らない部分があった時に、画像をインプットして「私は何が気に入らないかわかりますか?」と聞く。その結果、Claudeが言い当てたならYesと答え、間違えたらなら「違います」、と伝えた上で正解を教える。という感じにすると、勘違い(Claudeが修正すべきだと思っている箇所)ではなく、ズバリ私が直してほしいと思ったところだけを修正してくれる確率が上がりました。
-
構造化出力のコツ
- これは基本だと思うですが、私がLLM人狼を作ったときにできていなかったので、戒めのために記載します。
- 意思決定や評価をLLMに行ってもらう場合は、方針や根拠を述べてもらってから意思決定(あるいは採点)してもらうようにすることで精度が上がります。
まとめ
今回はローカル LLM を用いたポートフォリオ生成アプリの紹介と、Claude MCP + filesystemを通じた開発における学びについてまとめました。
今までフロントエンドなんて考えてこなかった私ですが、一度知ってしまうとそこにこだわりが出てしまい時間が溶けていきます笑
まあ今作っているアプリでローカルLLMが活躍するのはバックエンドの方なので、あまりフロントエンド沼にハマらないように注意しながら開発を進めていきたいと思います。本当に作りたいのはここからなので、できれば年末年始と年明けの3連休で形に出来たらなと思っています。
今年書く記事としてはこれが最後になります。それでは皆さん、よいお年を!
最後まで読んでいただきありがとうございました。次回もぜひよろしくお願いします。
おまけ:モデルごとの最高のポートフォリオ
ここではおまけとして、いくつかのモデルで資本主義を完全に理解した「資本主義の哲人」という異名を持つ設定の仮想キャラクターで、ポートフォリオを作ってもらいました。ポートフォリオもそうですが、投資根拠もモデルごとに個性が出ていて面白いです。
投資哲学やポートフォリオとしては、gemma-2-27b-itが個人的に好みです。
それと、プロンプトの影響もあると思いますが、他のモデルだと自分のパラメータなどのメタ発言をしているのが多いですね。あと何故か犯罪係数が高い→レバレッジ投資をするという発想のLLMが多かったです(レバレッジ投資自体は、犯罪ではないはずですが笑)
-
gemma-2-27b-it.f16.Q8_0
-
qwen2.5:32b-instruct-q4_K_M
- phi-4:f16
- command-r-plus:104b-08-2024-q4_K_M
- Athene-V2-Chat:Q4_K_M
Discussion