1
1

Delete article

Deleted articles cannot be recovered.

Draft of this article would be also deleted.

Are you sure you want to delete this article?

4B→14B、34KB→9KB:自分の業務を支援するローカルLLMを作って詰まった5つのこと

1
Posted at

アプリ・システム開発の相談を受けたときに、必要な情報をヒアリングし、技術を選び、要件を整理し、概算見積まで支援するAIを試作しました。

今回目指したのは私の口調を真似するチャットボットではなく、案件ごとに「次に何を確認するか」「MVPに何を残すか」「どの技術を選ぶか」といった、上流工程における判断の支援ができるAIの開発です。

学習・参照用の素材として用意したのは、noteの公開記事152本と下書き73本の計225本、過去に実際に発行した40件以上の見積書です。推論環境にはOllamaを使い、ローカルLLMで動かしました。

完成した機能よりも、実装中に詰まった点の方が参考になると思ったので、この記事では次の5点を中心にまとめます。

  • 4Bモデルでは、数ターンで会話の目的を見失った
  • 34KBのシステムプロンプトに知識を詰めると、重要な指示が埋もれた
  • LLMに見積計算を任せると、明細と合計が一致しなかった
  • 「質問は一度に一つ」という指示を守らせきれなかった
  • モデルの技術知識が古く、現在の選択肢を考慮できなかった

作ったもの

ユーザーが作りたいサービスについて自由に入力すると、AIが不足している情報を一問ずつ確認します。

たとえば「植物診断アプリを作りたい」という相談なら、次のような情報を確認します。

  • 誰が使うのか
  • 何を診断するのか
  • 診断結果として何を返すのか
  • iOS、Android、Webのどこで提供するのか
  • 画像認識や生成AIが本当に必要か
  • 管理画面は必要か
  • 予算と希望時期はどの程度か

全体を一つのLLMへ任せない

最初に整理したのは、情報と処理の役割です。

情報・処理 役割 扱い方
noteや過去案件の経験 判断の根拠となる知識 必要な内容だけRAGで参照する
判断原則 質問・提案の進め方 短く整理して常に渡す
過去の見積 機能別の価格レンジ マスタデータとして構造化する
小計・消費税・合計 必ず一致すべき計算 アプリ側で計算する
最新の技術情報 変化が速い知識 更新可能な技術メモとして参照する
一度に一問だけ聞く制約 必ず守りたい動作 サーバー側でも検証する

LLMに向いているのは、曖昧な相談文を読み取り、次に確認すべきことを考え、自然な文章で返す処理です。

一方、金額計算、出力形式、質問数の上限など、毎回同じ結果にならなければ困る処理は通常のプログラムに向いています。

実際の処理は、おおむね次のように分けています。

  1. ユーザーが相談内容を入力する
  2. サーバーが会話履歴とヒアリング状況を整理する
  3. 必要な判断原則、関連情報、技術メモを選ぶ
  4. ローカルLLMが次の質問または提案を生成する
  5. サーバーが質問数、出力形式、見積計算を検証する
  6. 問題がなければチャットUIへ表示する

詰まったこと1:4Bでは会話の目的を維持できなかった

最初は、手元にあった4Bクラスのモデルから試しました。

しかし、複数ターンのヒアリングは安定しませんでした。「植物診断アプリを作りたい」という相談に対して、最初は「誰が使いますか?」と聞けても、「植物を育てている人です」と返すと、園芸の一般的なアドバイスを始めてしまいます。

本来の目的はアプリ開発の要件整理ですが、直前の「植物」という話題に引っ張られていました。同じ質問を繰り返すこともありました。

プロンプト調整だけでは十分に改善しなかったため、日本語性能を重視してSwallow系の8Bモデルへ変更しました。すると脱線と質問の繰り返しはかなり減り、最終的には14Bクラスまで上げるとほとんどなくなりました。

今回の条件では、モデルを大きくすることで、会話履歴、判断原則、参照情報を同時に扱う安定性が上がりました。

もちろん、すべての4Bモデルが使えないという話ではありません。分類、抽出、短い文章の整形など、入出力が限定された処理なら小さいモデルでも十分な場合があります。一方で、複数ターンの会話と実務判断を同時に求めると、指示追従性と推論の安定性が土台になると感じました。

詰まったこと2:34KBのプロンプトに知識を詰めると、指示が埋もれた

当初は、見積マスターと判断原則の全文、合計約34KBをシステムプロンプトへ入れていました。

情報量を増やせば回答も良くなると考えていましたが、結果は逆でした。「質問は一度に一つ」といった重要な指示が、大量の知識に埋もれて守られにくくなり出力の形式が不安定になりました。

そこで、毎回必要な判断だけを約9KBのダイジェストへ圧縮しました。詳しい知識は、相談内容に関係するものだけを検索して渡す構成へ変更しました。

このとき分かったのは、コンテキスト上限に収まることと、モデルがすべての情報を同じ精度で使えることは別物だということです。

「入るから入れる」のではなく、次のように分けた方が安定しました。

  • 毎回必要な短い原則はシステムプロンプト
  • 量が多い過去資料はRAG
  • 頻繁に変わる情報は更新可能な外部データ
  • 必ず守る処理はコード

詰まったこと3:見積の計算をLLMに任せると、数字が合わない

LLMに見積書を作らせると、各明細は自然に見えても、小計や合計が一致しないことがありました。

そこで、LLMには必要な機能と明細の候補を出させ、小計、消費税、合計はアプリ側で再計算するようにしました。LLMが合計金額を書いても、その数字は使いません。

本番運用を考えるなら、LLMから自由な金額を返させるより、次のように機能IDと数量だけを構造化して返させる方が安全です。

{
  "items": [
    { "feature_id": "auth_email", "quantity": 1 },
    { "feature_id": "push_notification", "quantity": 1 },
    { "feature_id": "admin_user_management", "quantity": 1 }
  ]
}

サーバー側はfeature_idを使ってマスターから単価を取得し、数量を掛け、税額と合計を計算します。存在しないIDや不正な数量もこの段階で弾けます。

LLMは「どの機能が必要か」という曖昧な判断を担当し、金額の確定は決定論的なコードへ戻す設計です。

詰まったこと4:「一問ずつ聞く」はプロンプトだけでは守られない

上流工程のヒアリングでは、一度に質問を並べすぎるとユーザーが答えにくくなります。そのため、システムプロンプトに「質問は一度に一つ」と書きました。

しかし、モデルはときどき複数の質問をまとめて返します。指示を強く書いても、完全には防げませんでした。

そこで、サーバー側で出力を解析し、複数の質問が含まれている場合は最初の一問だけを表示する処理を加えました。

ここでも考え方は同じです。守れなかったときにユーザー体験が崩れる制約は、プロンプトだけに依存せず、アプリケーション側でも担保します。

より厳密にするなら、自由文だけを返させるのではなく、出力を次のような状態として扱う方法もあります。

{
  "action": "ask",
  "question": "このアプリを主に利用するのは誰ですか?",
  "hearing_key": "target_user"
}

actionhearing_keyをサーバー側で検証すれば、会話を管理できます。

詰まったこと5:技術知識はモデルの中で更新されない

画像診断の実装方法を聞いたところ、モデルが古い前提で回答し、現在の主要なマルチモーダルAIを考慮しない提案を返すことがありました。

AI、クラウド、OS、ストア審査、ライブラリなどは変化が速いため、モデル内部の知識だけに依存するのは危険です。

そこで、最新の技術情報はモデルへ覚えさせるのではなく、更新可能な技術メモとして分離しました。必要なときだけ検索して渡せるようにしておけば、モデル自体を入れ替えたり再学習したりせずに情報を更新できます。

更新頻度で情報を分けると整理しやすくなります。

情報 更新頻度 置き場所
質問の進め方やMVPの考え方 低い 短い判断原則
過去案件の経験 中程度 RAGの参照データ
ライブラリやストア審査の情報 高い 更新可能な技術メモ
価格や税率 業務ルール次第 マスター・設定値

自然な回答と、正しい判断は別だった

回答が自然だと、それだけで正しいように見えます。しかし、上流工程では質問の抜け、不要な機能の追加、技術選定の偏り、見積の漏れが実害につながります。

そのため、評価では文章の自然さだけでなく、実案件に近い確認項目を用意しました。

  • 必須の質問を漏らしていないか
  • すでに回答されたことを再度聞いていないか
  • 顧客の了承なく仕様を追加していないか
  • MVPと将来機能を分けられているか
  • AIが不要な部分にAIを提案していないか
  • 見積明細と合計が一致しているか

「良い回答」の例だけでなく、「してはいけない判断」も評価項目に入れることでこのLLM自体の信頼度を上げれるように努めました。

ローカルLLMを選ぶときの注意

今回は案件情報や見積を扱うため、ローカルLLMで試作しました。ただし、ローカルで動くこと自体が安全性を保証するわけではありません。

  • 会話ログをどこへ保存するか
  • PCやストレージを暗号化しているか
  • 誰がモデルとデータへアクセスできるか
  • バックアップへ機密情報が複製されないか
  • モデルのライセンスが用途に合っているか

こうした設計は別途必要です。機密情報を外部へ送れない要件がない場合は、クラウドAPIの方が導入・運用コストを抑えられるケースもあります。

まとめ

今回の試作で、実務を支援するAIは大量の資料をLLMへ渡すだけでは作れないと分かりました。

  • 判断のやり方を先に言語化する
  • 大量の知識は必要なときだけ参照する
  • 常に必要な指示は短く保つ
  • 計算と必須制約はコードで担保する
  • 変化の速い情報は外から更新できるようにする
  • 実案件に近いシナリオで判断を評価する

今回はRAG、判断原則をまとめたプロンプト、コードを組み合わせています。

1
1
0

Register as a new user and use Qiita more conveniently

  1. You get articles that match your needs
  2. You can efficiently read back useful information
  3. You can use dark theme
What you can do with signing up
1
1

Delete article

Deleted articles cannot be recovered.

Draft of this article would be also deleted.

Are you sure you want to delete this article?