Claude Code × Medical Application

【Claude Code】社内の BI ダッシュボードを AI ダッシュボードに Part3:生成 AI の組み込み — AI に委ねる範囲の設計

1. はじめに — AI に何を委ねるか

社内の BI ダッシュボードに生成 AI を入れるとき、最初に決めるのはAI に何を委ねるかです。質問に答えて集計まで任せるのか、画面の操作だけを任せるのか。ここで決めた範囲が、数字の正しさ、テストのしかた、費用、すべてを左右します。

Part2 までで、照合を通った数字が画面に出るところまでができました。Part3 は、そこに「話しかけると動く」を足す回です。

前作の連載「Medicare Part D × Text-to-SQL」では、AI に SQL を書かせ、集計そのものを任せました。今回は逆に、AI には画面の条件を選ばせるだけにしています。

Text-to-SQL と、条件を選ばせる方式の違い
自由に探るなら SQL 型、決まった問いの数字を多くの人に配るなら条件を選ぶ型

この回の構成です。

  1. はじめに(この章)
  2. 委ねる範囲を、画面の型で決める
  3. 指示文に書いたこと
  4. 画面に渡す前の4つの関所
  5. テストを3段に分ける
  6. テストが通っても、説明文は人が読む
  7. 揺れは、サーバー側の決まりで止める
  8. 今回のハーネス/まとめ

2. 委ねる範囲を、画面の型で決める

2-1. 画面の状態を1つの型にする

画面を作る段階で、画面の状態を1つの型(ViewState)にまとめました。どの画面を見ているか、年度、MDC、疾患、手術の分岐、都道府県、二次医療圏、施設。地図もランキングも推移も、すべてこの1つの型から描き、URL のクエリにも同じ名前で入れます。

こうしておくと、AI の仕事は「質問を読んで、この型を埋めること」だけになります。AI が選んだ条件は、閲覧者が手で選んだ条件と同じ形で画面に渡り、URL に残り、チップとして画面に出ます。違っていれば閲覧者がその場で直せます。

話しかけると動く仕組み。AI は画面の条件を選ぶだけで、数字は照合済みの表から画面が出す
AI が知っているのは名前とコードだけ。件数は一度も渡さない

2-2. 道具は3つだけ

AI(Claude Haiku 5.5)に渡す道具は3つです。

道具 役割 返すもの
find_codes 言葉をコードにする(「循環器」「心不全」「札幌」「PCI」→ 画面で選べる値) 名前とコードだけ。件数は返さない
set_view 画面を決める(ViewState の各項目と、短い説明、答えられないときの理由) 画面の条件
decline 断る(関係ない質問・指示の書き換え・医療の相談・見つからない病院) 種類だけ。断りの文はこちらで決めたもの

ポイントは、find_codes が件数を返さないことです。AI は「榊原記念病院」のコードは知っていても、その病院の件数は一度も見ません。だから、AI が数字を作ったり、非公表の値を0として足したりする事故が、仕組みの上で起きません。

set_view の値は、選べる値の一覧(都道府県・年度など)を道具の定義の中に列挙し、厳密な形(strict)で返させています。存在しない値は、そもそも返しにくくなります。

3. 指示文に書いたこと

指示文(システムプロンプト)は、AI の役割を「画面の操作係」と決めるところから始めました。中心になるのは次の5つです。

  • あなたの仕事:質問を読み、画面の状態を set_view で決める。疾患・手術・医療圏・病院名は、先に find_codes で確かめた値だけを使う
  • 説明は短い1文:選んだ条件だけを書く。件数・施設数・順位・割合などの数字は書かない。あなたは数字を知らない。数字は画面が公表データから出す
  • 答え方の選び方:「多い病院」→ ランキング、「〜ごとに比べて」→ 地域のランキング、「3年分」→ 推移、「AとBを比べて」→ 比較
  • 各画面が見せるもの:推移の画面は、地域の合計の3年度と、上位10施設それぞれの3年度を出す(6章で足した一文)
  • 聞かれていない条件は変えない:地域・年度・手術など、質問に出てこない条件は今の画面のまま(6章で足した一文)

指示文は毎回同じなので、キャッシュ(prompt caching)から読ませています。1問で AI を1〜3回呼び、入力は約200〜2,000トークン、出力は約450〜650トークンでした。モデルの名前と料金は、記憶に頼らず公式の料金ページで確かめてから使っています(入力 0.10ドル・出力 0.50ドル/100万トークン)。1問あたり約0.1円です。

4. 画面に渡す前の4つの関所

指示文で「数字を書かない」と頼んでも、AI がそれを守るとは限りません。そこで、破られても画面がおかしくならないように、AI の返答を画面に渡す前に、サーバー側で4つの関所を通しています。

AI の返答は、画面に渡す前に4つの関所を通す。値は選択肢にあるか・説明文に数字はないか・字と言語は正しいか・画面の決まりに合わせる
どれも指示文に頼らず、サーバーのコードで確かめる
  1. 値は画面の選択肢にあるか:存在しない年度や医療圏は通しません。画面から届く「今の状態」も信用せず、AI の返答と同じ検査を通します
  2. 説明文に数字はないか:AI には件数を渡していないので、説明文に「〇件」「〇位」が出たら、それは AI が作った数字です。説明文ごと捨て、決まった文に差し替えます。テストでは「千葉西総合病院が9,265件で1位です」という説明が差し替わることを確かめました
  3. 字と言語は正しいか:断りの返答に中国語の字(救急车)が混じったことがありました。断りの文は AI に書かせず、種類ごとの決まった文にしました。条件を選んだときの説明文に簡体字が混じったら、エラーとして返して書き直させます
  4. 画面の決まりに合わせる:比較の画面では疾患を外す、など。7章で足した決まりです

AI が道具を使わずに文章だけを返したときも、画面は変えません。画面を動かせるのは、関所を通った set_view だけです。

5. テストを3段に分ける

5-1. 呼ばないテスト、本物の API、揺れの確かめ

AI を組み込んだアプリのテストは、本物の API を呼ぶと費用がかかり、答えも揺れます。Claude Code には、最初から「本物の API を呼ぶテストと呼ばないテストを分ける」ように頼みました。

テストを3段に分ける。呼ばないテスト(毎回)、本物の API の質問ごと(直したとき)、揺れの確かめ(収録の前に5回ずつ)
下の段ほど費用がかかるので、回数を絞る
  • 呼ばないテスト:返答の検査、決まった断りの文、画面の決まりなど。AI の返答を用意した値で差し替えて確かめる。何度走らせても費用はかからない
  • 本物の API:質問ごと:デモの4問と、断るべき4問(天気・指示の書き換え・薬の相談・存在しない病院)。8問すべてが期待どおりの画面の状態になり、断るべき4問は画面を変えず、説明文に数字も出なかった
  • 本物の API:揺れの確かめ:同じ質問を5回ずつ。7章で使った

本物の API を呼ぶテストは、Anthropic に専用のワークスペースを作り、月額の上限を設けた鍵で走らせています。本番の回数制限を使わないよう、HTTP の窓口を通さず、手元で関数を直接呼ぶ形にしました。

5-2. テストを動かすまでのつまずき

本物の API を呼ぶテストは、最初は動きませんでした。

  • 鍵を書く設定ファイル(.dev.vars)が空のとき、読み込みの正規表現が改行をまたいで次の行(日本語のコメント)を鍵として拾い、通信の前に失敗した。空なら「鍵なし」として飛ばすように直した
  • テストの待ち時間の既定(5秒)が、AI を2回呼ぶ時間より短く、3問が時間切れになった(答え自体は正しかった)。60秒にした。テストの道具が通ったテストの出力を出さないので、結果はファイルに書く形にした

どちらも、Claude Code が失敗のメッセージから原因を突き止めて直しました。人がやったのは、ワークスペースと上限を用意して鍵を入れることです。

6. テストが通っても、説明文は人が読む

6-1. 8問とも通ったのに

本物の API のテストは、8問すべてが期待どおりの画面の状態になりました。それでも、人が説明文を読むと、直したい点が2つありました。

  • 質問1(東京都で循環器の症例が多い病院を3年分)で、「3年分の施設別ランキングは公開データにない」と要らない断りを付けた。推移の画面は上位10施設の3年度を出すので、答えられる
  • 質問3(2つの病院の比較)で、聞かれていない都道府県(東京)を選んだ

テストが確かめていたのは「画面の状態の必要な項目が正しいか」で、説明の言い回しや、余計な条件までは見ていませんでした。原因は、AI に「各画面が何を見せるか」と「聞かれていない条件は変えない」を伝えていなかったことです。指示文に足して直し、本物の API のテストにも「質問1で断りが付かない」「質問3で地域の条件が変わらない」を加えました。

6-2. 断りは1回だけ

質問4(全国の心不全の3年推移)は、公開データだけでは答えられない質問です。疾患ごとの件数は令和6年度の分しか公開されていないので、心不全だけの3年推移は出せません。

質問4:心不全の令和6年度の件数順に並べ、推移は循環器全体で示す。理由は画面の先頭に1回だけ

最初の版では、同じ断りが返答文・「できないこと」の欄・推移の画面の先頭の3か所に出て、くどくなっていました。返答文は選んだ条件だけの短い1文にし、理由は画面の先頭に1回だけ出す形にしています。これも、テストではなく、人が画面を見て決めたことです。

7. 揺れは、サーバー側の決まりで止める

7-1. まっさらな画面からでは足りなかった

デモ動画を撮る前に、デモの4問を5回ずつ聞き、AI が選ぶ画面の状態が毎回同じかを確かめました。まっさらな画面から聞くと、期待の項目は20回とも一致しました。

ところが、収録と同じ順に、前の場面の条件を引き継いで聞き直すと揺れました。比較の質問で、前の質問の疾患や「手術あり」を引き継いだり外したり、質問4で北海道や比較の2病院を引き継いだり。実際の画面は、まっさらな状態から使われるとは限りません。

AI の揺れは、指示文ではなくサーバー側の決まりで止める。収録と同じ順で5回ずつ聞くと揺れ、決まりを足すと5回とも同じに
揺れたのは比較と質問4の場面

7-2. 指示文に頼らず、決まりにする

ここは指示文で頼むのをやめ、サーバー側の決まりにしました。

  • 比較・施設の詳細は、地域と疾患を使わない画面。地域は今のまま保ち、疾患と分岐は外す
  • 手術の分岐を選んだら、手術の有無は「すべて」にそろえる(分岐が優先されるので画面は同じ。揺れの元を断つ)

足したあと、収録と同じ順で5回通して、全場面で URL が5回とも同じになりました。返答文は毎回少し違いますが、それは画面に影響しません(動画の字幕でも、返答文は読み上げない書き方にしています)。

7-3. 言い回しを並べると、かえって誘う

逆の失敗もありました。質問4の英語の返答に断りが混じった件を直そうとして、指示文に具体的な言い回し(「MDC 単位で示す」など)を並べたところ、日本語の質問1に要らない「できないこと」が付くようになりました。言い回しを並べると、かえってその言葉を誘うようです。一般的な一文に戻しています。

要らない「できないこと」は、直したあとの版でも9回中1回は出ました。前からある揺れと同じ程度です。ここは決まりにしにくいので、動画の撮影では「付いたら撮り直す」ことにしました。止めきれない揺れは、使う場面の手順で吸収するのも1つの方法です。

8. 今回のハーネス

道具 このリポジトリでの実体 役割
画面の型 ViewState(URL と同じ名前) AI の仕事を「型を埋める」だけにする
道具の定義 find_codes・set_view・decline(strict) 件数を渡さない。選べる値を列挙する
関所 サーバーの検査(値・数字・字・画面の決まり) 頼んだことが破られても画面を守る
テストの3段 呼ばないテスト/本物の API/揺れの確かめ 費用と揺れに合わせて回数を分ける
専用のワークスペース 月額の上限つきの鍵 テストの費用に天井を付ける
人の判断 説明文を読む、断りの出し方、撮り直しの基準 テストにできないことを見つけ、テストに足す

9. まとめ

  • AI に委ねる範囲は、画面の型で決めた。AI は型を埋めるだけで、件数には一度も触れない
  • 指示文は「頼む」場所、サーバーは「確かめる」場所。返答は4つの関所を通してから画面に渡す
  • テストは、呼ばないもの・本物の API・揺れの確かめの3段に分けた。テストが通っても、説明文は人が読む
  • AI の揺れは、指示文ではなくサーバー側の決まりで止めた。止めきれない揺れは、使う場面の手順で吸収した

AI に委ねる範囲を狭く決めるほど、AI は安心して使えます。

次のステップ

Part4(近日公開)では、この AI ダッシュボードを公開し、運用するところを扱います。誰でも使える公開のデモで費用が膨らまないようにした三重の上限、入口で1回だけ通すボット対策、スマホの初回表示を測ってから直したこと、人にしか任せないことを決めた公開の手順を紹介します。

出典

  • Anthropic「Pricing」(Claude Haiku 5.5、2026年10月24日確認)。https://www.anthropic.com/pricing
  • Anthropic, Claude Docs(Tool use / Prompt caching)
  • 厚生労働省「退院患者調査」令和4〜6年度 結果報告(画面の数字の出典)
  • 本記事の図表・画面は株式会社HerzLebenが作成したもので、国が作成したものではありません