[{"data":1,"prerenderedAt":-1},["ShallowReactive",2],{"blogEntry::post\u002Fcodatum-ai:ja":3},{"title":4,"slug":5,"description":6,"body":7,"author":8,"category":9,"coverImageUrl":13,"ogImageUrl":14,"createdAt":15,"updatedAt":16,"datePublished":17,"locale":18,"related":19},"CodatumのダッシュボードにAI生成サマリを追加する","codatum-ai","複数チャートを配置して、パラメータで出力内容を変えられるCodatumのダッシュボード。テキストサマリは、手動で書くと更新が追いつか図、パラメータを反映することもできません。CodatumのテキストパネルとBigQuery経由のVertex AIを組み合わせて、ユーザーの操作に応じてサマリーを自動生成する仕組みを紹介します。","\u003Cp>このブログは、実際に\u003Ca href=\"https:\u002F\u002Fcodatum.jp\u002Ftemplates\u002Fai-summary-dashboard\" target=\"_blank\" rel=\"noopener noreferrer\">Codatumのテンプレート\u003C\u002Fa>を確認しながら読んでいただくことができます！\u003C\u002Fp>\u003Cp>ぜひこちらのテンプレートを参照の上、手を動かしなら読んでみてください。\u003C\u002Fp>\u003Cp>\u003C\u002Fp>\u003Cp>Codatumのダッシュボードは、チャートやテキストなどを自由度高く掲載することができるため、用途にあったバラエティ豊かな活用をいただくことができます。\u003C\u002Fp>\u003Cp>ダッシュボードにテキストサマリを掲載することで、グラフだけでは読み取りにくい傾向や背景がユーザーに伝わりやすくなります。\u003C\u002Fp>\u003Cfigure class=\"EmbeddedContent_Wrapper\">\u003Cimg src=\"https:\u002F\u002Fimages.ctfassets.net\u002Fggtw2zqmifs5\u002F3VsENMhl1ncj0OB078IRQX\u002Facff6eb1f1504381c8ef66b4cd0046b4\u002Fdc5f925c-7e19-472a-813f-346dbc0e03ea.png\" alt=\"スクリーンショット 2026-08-14 9.46.28\">\u003C\u002Ffigure>\u003Cp>ただ、このサマリーを人が手動で書いている場合、更新の手間がかかるだけでなく、ユーザーがパラメータを変更してデータの対象を切り替えても、文章の方はその操作についてこられません。\u003C\u002Fp>\u003Cp>企業を絞り込んだのに、サマリーは全社データを前提にした内容のまま。担当者が定期的に書き直さない限り、グラフとテキストの間にズレが生まれてしまいます。\u003C\u002Fp>\u003Cp>そこで、この記事では、BigQueryを介してVertex AIを呼び出し、ユーザーがパラメータで指定したデータに応じて、サマリーそのものをその場で生成する方法を紹介します。\u003C\u002Fp>\u003Cp>BigQuery以外のコネクションでも、対応するAI機能があれば同じ考え方で実現できます。\u003C\u002Fp>\u003Cp>※Vertex AIのセットアップについては、\u003Ca href=\"https:\u002F\u002Fcodatum.jp\u002Fblog\u002Fpost\u002Fbigquery-vertex-ai\" target=\"_blank\" rel=\"noopener noreferrer\">こちら\u003C\u002Fa>の記事にてご紹介しています\u003C\u002Fp>\u003Cp>\u003C\u002Fp>\u003Ch2>\u003Cb>テキストパネルで、生成したサマリーを表示する\u003C\u002Fb>\u003C\u002Fh2>\u003Cp>Codatumには、Markdown記法のテキストを表示するための「テキストパネル」というチャートタイプがあります。今回は、このテキストパネルをAIが生成した文章の表示先として使います。\u003C\u002Fp>\u003Cfigure class=\"EmbeddedContent_Wrapper\">\u003Cimg src=\"https:\u002F\u002Fimages.ctfassets.net\u002Fggtw2zqmifs5\u002F26jbZSbxBNd4xBX8ZTpPGi\u002F59acfe91762e8714dd9c8ed9562d1094\u002Fecbe169e-363a-420b-a0e2-be9595ebe858.png\" alt=\"スクリーンショット 2026-08-14 9.50.03 1\">\u003C\u002Ffigure>\u003Cp>やることは大きく分けて4つです。\u003C\u002Fp>\u003Cul>\u003Cli>\u003Cp>Vertex AIをセットアップする\u003C\u002Fp>\u003C\u002Fli>\u003Cli>\u003Cp>BigQueryにモデルを作成する\u003C\u002Fp>\u003C\u002Fli>\u003Cli>\u003Cp>集計データをモデルに渡す\u003C\u002Fp>\u003C\u002Fli>\u003Cli>\u003Cp>テキストパネルチャートで生成結果を表示する\u003C\u002Fp>\u003C\u002Fli>\u003C\u002Ful>\u003Cp>この流れを組んでおくと、ユーザーがパラメータを変更してクエリが再実行されるたびに、その時点で表示されているデータに応じたサマリーが自動的に生成されます。\u003C\u002Fp>\u003Cp>クエリの実行に合わせてサマリも書き変わるため、データの更新に合わせて、手動で更新することなく、最新・最適なサマリを閲覧することができます。\u003C\u002Fp>\u003Cp>\u003C\u002Fp>\u003Ch2>\u003Cb>実装例：Chicago Taxi Tripデータで検証する\u003C\u002Fb>\u003C\u002Fh2>\u003Cp>ここからは、BigQueryのパブリックデータセット「Chicago Taxi Trips」を使った実装例を掲載します。\u003C\u002Fp>\u003Cp>企業（Company）と支払い方法（Payment Type）をパラメータとして切り替えると、その都度対象データに応じたサマリーが生成され、表示が変わります。\u003C\u002Fp>\u003Cp>\u003C\u002Fp>\u003Ch3>\u003Cb>モデルの作成\u003C\u002Fb>\u003C\u002Fh3>\u003Cfigure class=\"EmbeddedContent_Wrapper\">\u003Cimg src=\"https:\u002F\u002Fimages.ctfassets.net\u002Fggtw2zqmifs5\u002F5vh4lvvsfHFcBo56gu0tGE\u002Ff7e06ef6d25a11dcf3fca17ce5af6bd8\u002F51764812-f202-44c9-bfc7-0dc2d76177d4.png\" alt=\"スクリーンショット 2026-08-14 9.53.47\">\u003C\u002Ffigure>\u003Cp>まず、Vertex AIのモデルをBigQuery上に作成します。この作業はBigQueryのクエリエディタ側でも実行できます。\u003C\u002Fp>\u003Cblockquote>\u003Cp>\u003Cpre>\u003Ccode class=\"hljs\">\u003Cspan class=\"hljs-keyword\">CREATE\u003C\u002Fspan> \u003Cspan class=\"hljs-keyword\">OR\u003C\u002Fspan> REPLACE MODEL `codatum\u003Cspan class=\"hljs-operator\">-\u003C\u002Fspan>example.example.vertex_ai`\nREMOTE \u003Cspan class=\"hljs-keyword\">WITH\u003C\u002Fspan> CONNECTION `us.vertex_ai_test`\nOPTIONS(\n  ENDPOINT \u003Cspan class=\"hljs-operator\">=\u003C\u002Fspan> \u003Cspan class=\"hljs-string\">'gemini-2.5-flash'\u003C\u002Fspan>\n)\u003C\u002Fcode>\u003C\u002Fpre>\u003C\u002Fp>\u003C\u002Fblockquote>\u003Cp>クエリが完了すると、BigQueryの\u003Ccode class=\"hljs\">example\u003C\u002Fcode>データセットに\u003Ccode class=\"hljs\">vertex_ai\u003C\u002Fcode>モデルが追加されます。\u003C\u002Fp>\u003Cp>\u003C\u002Fp>\u003Ch3>\u003Cb>データの集計\u003C\u002Fb>\u003C\u002Fh3>\u003Cp>次に、サマリーの元になるデータを集計します。ここでは、月次で企業ごと・支払い方法ごとの乗車回数、乗車時間、乗車距離、乗車料金を集計し、企業名と支払い方法はCodatumのパラメータ機能でユーザー側から変更できるようにします。\u003C\u002Fp>\u003Cp>ただし、対象テーブルが数億行規模でパーティション\u002Fクラスタリングが無い場合、絞り込み条件を集計クエリのWHERE句にそのまま入れると、パラメータを切り替えるたびに生データ全体への高コストなスキャンが発生してしまいます。そこで集計はあらかじめ1回だけ実行し、月次×企業×支払い方法の粒度で小さな中間テーブルに保存しておき、Codatum側のパラメータはこの軽量なテーブルに対してのみ絞り込みを行うようにします。\u003C\u002Fp>\u003Cfigure class=\"EmbeddedContent_Wrapper\">\u003Cimg src=\"https:\u002F\u002Fimages.ctfassets.net\u002Fggtw2zqmifs5\u002F7uTBNcFIwDI2Vy8bNe2Wr6\u002F82c422ac091d88e2c01444766f1ca054\u002F5b075cd6-bb92-404b-819b-9b291f78d7d9.png\" alt=\"スクリーンショット 2026-08-14 10.55.42\">\u003C\u002Ffigure>\u003Cp>\u003Cb>① 事前集計（BigQueryコンソール等で単発、または定期実行。Codatumの外で実行）\u003C\u002Fb>\u003C\u002Fp>\u003Cblockquote>\u003Cp>\u003Cpre>\u003Ccode class=\"hljs\">\u003Cspan class=\"hljs-keyword\">CREATE\u003C\u002Fspan> \u003Cspan class=\"hljs-keyword\">OR\u003C\u002Fspan> REPLACE \u003Cspan class=\"hljs-keyword\">TABLE\u003C\u002Fspan> `your\u003Cspan class=\"hljs-operator\">-\u003C\u002Fspan>project.your_dataset.monthly_company_payment_summary` \u003Cspan class=\"hljs-keyword\">AS\u003C\u002Fspan>\n\u003Cspan class=\"hljs-keyword\">SELECT\u003C\u002Fspan>\n  DATE_TRUNC(trip_start_timestamp, \u003Cspan class=\"hljs-keyword\">month\u003C\u002Fspan>) \u003Cspan class=\"hljs-keyword\">as\u003C\u002Fspan> \u003Cspan class=\"hljs-keyword\">month\u003C\u002Fspan>,\n  company,\n  payment_type,\n  \u003Cspan class=\"hljs-built_in\">COUNT\u003C\u002Fspan>(\u003Cspan class=\"hljs-keyword\">DISTINCT\u003C\u002Fspan> unique_key) \u003Cspan class=\"hljs-keyword\">as\u003C\u002Fspan> trip_count,\n  \u003Cspan class=\"hljs-built_in\">SUM\u003C\u002Fspan>(trip_seconds) \u003Cspan class=\"hljs-operator\">\u002F\u003C\u002Fspan> \u003Cspan class=\"hljs-number\">60\u003C\u002Fspan> \u003Cspan class=\"hljs-keyword\">as\u003C\u002Fspan> total_trip_min,\n  \u003Cspan class=\"hljs-built_in\">AVG\u003C\u002Fspan>(trip_seconds) \u003Cspan class=\"hljs-operator\">\u002F\u003C\u002Fspan> \u003Cspan class=\"hljs-number\">60\u003C\u002Fspan> \u003Cspan class=\"hljs-keyword\">as\u003C\u002Fspan> average_trip_min,\n  \u003Cspan class=\"hljs-built_in\">MAX\u003C\u002Fspan>(trip_seconds) \u003Cspan class=\"hljs-operator\">\u002F\u003C\u002Fspan> \u003Cspan class=\"hljs-number\">60\u003C\u002Fspan> \u003Cspan class=\"hljs-keyword\">as\u003C\u002Fspan> max_trip_min,\n  \u003Cspan class=\"hljs-built_in\">MIN\u003C\u002Fspan>(trip_seconds) \u003Cspan class=\"hljs-operator\">\u002F\u003C\u002Fspan> \u003Cspan class=\"hljs-number\">60\u003C\u002Fspan> \u003Cspan class=\"hljs-keyword\">as\u003C\u002Fspan> min_trip_min,\n  \u003Cspan class=\"hljs-built_in\">SUM\u003C\u002Fspan>(trip_miles) \u003Cspan class=\"hljs-keyword\">as\u003C\u002Fspan> total_trip_miles,\n  \u003Cspan class=\"hljs-built_in\">AVG\u003C\u002Fspan>(trip_miles) \u003Cspan class=\"hljs-keyword\">as\u003C\u002Fspan> average_trip_miles,\n  \u003Cspan class=\"hljs-built_in\">MAX\u003C\u002Fspan>(trip_miles) \u003Cspan class=\"hljs-keyword\">as\u003C\u002Fspan> max_trip_miles,\n  \u003Cspan class=\"hljs-built_in\">MIN\u003C\u002Fspan>(trip_miles) \u003Cspan class=\"hljs-keyword\">as\u003C\u002Fspan> min_trip_miles,\n  \u003Cspan class=\"hljs-built_in\">SUM\u003C\u002Fspan>(fare) \u003Cspan class=\"hljs-keyword\">as\u003C\u002Fspan> total_fare,\n  \u003Cspan class=\"hljs-built_in\">AVG\u003C\u002Fspan>(fare) \u003Cspan class=\"hljs-keyword\">as\u003C\u002Fspan> average_fare,\n  \u003Cspan class=\"hljs-built_in\">MAX\u003C\u002Fspan>(fare) \u003Cspan class=\"hljs-keyword\">as\u003C\u002Fspan> max_fare,\n  \u003Cspan class=\"hljs-built_in\">MIN\u003C\u002Fspan>(fare) \u003Cspan class=\"hljs-keyword\">as\u003C\u002Fspan> min_fare\n\u003Cspan class=\"hljs-keyword\">FROM\u003C\u002Fspan>\n  `bigquery\u003Cspan class=\"hljs-operator\">-\u003C\u002Fspan>public\u003Cspan class=\"hljs-operator\">-\u003C\u002Fspan>data.chicago_taxi_trips.taxi_trips`\n\u003Cspan class=\"hljs-keyword\">WHERE\u003C\u002Fspan> trip_start_timestamp \u003Cspan class=\"hljs-operator\">&gt;=\u003C\u002Fspan> \u003Cspan class=\"hljs-string\">'2017-01-01'\u003C\u002Fspan> \u003Cspan class=\"hljs-keyword\">AND\u003C\u002Fspan> trip_start_timestamp \u003Cspan class=\"hljs-operator\">&lt;\u003C\u002Fspan> \u003Cspan class=\"hljs-string\">'2018-01-01'\u003C\u002Fspan> \u003Cspan class=\"hljs-comment\">-- 2017年のデータ\u003C\u002Fspan>\n  \u003Cspan class=\"hljs-keyword\">AND\u003C\u002Fspan> trip_seconds \u003Cspan class=\"hljs-operator\">!=\u003C\u002Fspan> \u003Cspan class=\"hljs-number\">0\u003C\u002Fspan> \u003Cspan class=\"hljs-keyword\">AND\u003C\u002Fspan> fare \u003Cspan class=\"hljs-operator\">!=\u003C\u002Fspan> \u003Cspan class=\"hljs-number\">0\u003C\u002Fspan> \u003Cspan class=\"hljs-keyword\">AND\u003C\u002Fspan> trip_miles \u003Cspan class=\"hljs-operator\">!=\u003C\u002Fspan> \u003Cspan class=\"hljs-number\">0\u003C\u002Fspan> \u003Cspan class=\"hljs-comment\">-- 外れ値除外\u003C\u002Fspan>\n  \u003Cspan class=\"hljs-keyword\">AND\u003C\u002Fspan> trip_seconds \u003Cspan class=\"hljs-operator\">&lt;\u003C\u002Fspan> \u003Cspan class=\"hljs-number\">21600\u003C\u002Fspan>\n\u003Cspan class=\"hljs-keyword\">GROUP\u003C\u002Fspan> \u003Cspan class=\"hljs-keyword\">BY\u003C\u002Fspan> \u003Cspan class=\"hljs-keyword\">month\u003C\u002Fspan>, company, payment_type\u003C\u002Fcode>\u003C\u002Fpre>\u003C\u002Fp>\u003C\u002Fblockquote>\u003Cp>\u003Cb>② Codatum側のSQLブロック（Codatum上で書くSQL。パラメータで動くのはここだけ）\u003C\u002Fb>\u003C\u002Fp>\u003Cp>templateのnotebookでは\u003Ccode class=\"hljs\">company_payment_agg\u003C\u002Fcode>として作成しています。\u003C\u002Fp>\u003Cblockquote>\u003Cp>\u003Cpre>\u003Ccode class=\"hljs\">\u003Cspan class=\"hljs-variable constant_\">SELECT\u003C\u002Fspan>\n  *\n\u003Cspan class=\"hljs-variable constant_\">FROM\u003C\u002Fspan>\n  \u003Cspan class=\"hljs-string\">`your-project.your_dataset.monthly_company_payment_summary`\u003C\u002Fspan>\n\u003Cspan class=\"hljs-variable constant_\">WHERE\u003C\u002Fspan>\n  \u003Cspan class=\"hljs-variable constant_\">CASE\u003C\u002Fspan> {\u003Cspan class=\"hljs-title class_\">Company\u003C\u002Fspan>} \u003Cspan class=\"hljs-variable constant_\">WHEN\u003C\u002Fspan> \u003Cspan class=\"hljs-string\">''\u003C\u002Fspan> \u003Cspan class=\"hljs-variable constant_\">THEN\u003C\u002Fspan> \u003Cspan class=\"hljs-variable constant_\">TRUE\u003C\u002Fspan> \u003Cspan class=\"hljs-variable constant_\">ELSE\u003C\u002Fspan> company = {\u003Cspan class=\"hljs-title class_\">Company\u003C\u002Fspan>} \u003Cspan class=\"hljs-variable constant_\">END\u003C\u002Fspan>\n  \u003Cspan class=\"hljs-variable constant_\">AND\u003C\u002Fspan> \u003Cspan class=\"hljs-variable constant_\">CASE\u003C\u002Fspan> {\u003Cspan class=\"hljs-title class_\">PaymentType\u003C\u002Fspan>} \u003Cspan class=\"hljs-variable constant_\">WHEN\u003C\u002Fspan> \u003Cspan class=\"hljs-string\">''\u003C\u002Fspan> \u003Cspan class=\"hljs-variable constant_\">THEN\u003C\u002Fspan> \u003Cspan class=\"hljs-variable constant_\">TRUE\u003C\u002Fspan> \u003Cspan class=\"hljs-variable constant_\">ELSE\u003C\u002Fspan> payment_type = {\u003Cspan class=\"hljs-title class_\">PaymentType\u003C\u002Fspan>} \u003Cspan class=\"hljs-variable constant_\">END\u003C\u002Fspan>\n\u003Cspan class=\"hljs-variable constant_\">ORDER\u003C\u002Fspan> \u003Cspan class=\"hljs-variable constant_\">BY\u003C\u002Fspan>\n  month\u003C\u002Fcode>\u003C\u002Fpre>\u003C\u002Fp>\u003C\u002Fblockquote>\u003Cp>\u003C\u002Fp>\u003Ch3>\u003Cb>AIモデルへのデータの受け渡し\u003C\u002Fb>\u003C\u002Fh3>\u003Cp>Codatumでは、SQLブロックの結果を別のSQLブロックから参照できます。この特性を使って、「集計」「JSON化」「配列結合」「プロンプト組み立て」「AI呼び出し」を役割ごとに分けて管理します。1本の複雑なクエリにまとめてしまうより、後から見直しやすくなります。\u003C\u002Fp>\u003Cfigure class=\"EmbeddedContent_Wrapper\">\u003Cimg src=\"https:\u002F\u002Fimages.ctfassets.net\u002Fggtw2zqmifs5\u002F4arPGdM1H6y8OzrOOQ4eF\u002Faf3d63a009da5b82274043bfd88d05e7\u002F407cf4f5-40a5-4826-8c65-325dc2585e6d.png\" alt=\"スクリーンショット 2026-08-14 11.28.49\">\u003C\u002Ffigure>\u003Cp>\u003C\u002Fp>\u003Cp>\u003Cb>①集計データを1行ずつJSON化\u003C\u002Fb>\u003C\u002Fp>\u003Cp>「集計データ」は、「データの集計」セクションで作成したSQLブロックを示しています。\u003C\u002Fp>\u003Cblockquote>\u003Cp>\u003Cpre>\u003Ccode class=\"hljs\">\u003Cspan class=\"hljs-keyword\">SELECT\u003C\u002Fspan>\n  TO_JSON_STRING(STRUCT(\n    \u003Cspan class=\"hljs-keyword\">month\u003C\u002Fspan>, company, payment_type, trip_count,\n    total_trip_min, average_trip_min, max_trip_min, min_trip_min,\n    total_trip_miles, average_trip_miles, max_trip_miles, min_trip_miles,\n    total_fare, average_fare, max_fare, min_fare\n  )) \u003Cspan class=\"hljs-keyword\">AS\u003C\u002Fspan> row_json\n\u003Cspan class=\"hljs-keyword\">FROM\u003C\u002Fspan>\n  集計データ\u003C\u002Fcode>\u003C\u002Fpre>\u003C\u002Fp>\u003C\u002Fblockquote>\u003Cp>②行ごとのJSONを1つの配列に結合\u003C\u002Fp>\u003Cblockquote>\u003Cp>\u003Cpre>\u003Ccode class=\"hljs\">\u003Cspan class=\"hljs-keyword\">SELECT\u003C\u002Fspan>\n  CONCAT(\u003Cspan class=\"hljs-string\">'['\u003C\u002Fspan>, STRING_AGG(row_json, \u003Cspan class=\"hljs-string\">','\u003C\u002Fspan>), \u003Cspan class=\"hljs-string\">']'\u003C\u002Fspan>) \u003Cspan class=\"hljs-keyword\">AS\u003C\u002Fspan> all_json\n\u003Cspan class=\"hljs-keyword\">FROM\u003C\u002Fspan>\n  JSON化した集計データ\u003C\u002Fcode>\u003C\u002Fpre>\u003C\u002Fp>\u003C\u002Fblockquote>\u003Cp>③プロンプトを組み立てる\u003C\u002Fp>\u003Cblockquote>\u003Cp>\u003Cpre>\u003Ccode class=\"hljs\">\u003Cspan class=\"hljs-variable constant_\">SELECT\u003C\u002Fspan>\n  \u003Cspan class=\"hljs-title function_\">CONCAT\u003C\u002Fspan>(\n    \u003Cspan class=\"hljs-string\">'以下のデータは月次のCompany別、PaymentType別のシカゴタクシー乗車データのサマリーです。'\u003C\u002Fspan>,\n    \u003Cspan class=\"hljs-string\">'月ごとの推移も含めて傾向を日本語でMarkdown形式のレポートとして要約してください。'\u003C\u002Fspan>,\n    \u003Cspan class=\"hljs-string\">'総乗車回数などの概要を説明した後、特徴的な項目を複数セクションに分けて説明してください。'\u003C\u002Fspan>,\n    \u003Cspan class=\"hljs-string\">'Markdown全体をコードブロックで囲わないでください。見出しや箇条書きなど、markdownの色々な要素を使ってください。'\u003C\u002Fspan>,\n    \u003Cspan class=\"hljs-string\">'生成したサマリーで完結させ、追加で編集はしません（追加の分析提案は可）。コードは埋め込まないでください。'\u003C\u002Fspan>,\n    \u003Cspan class=\"hljs-string\">'対象企業は'\u003C\u002Fspan>, \u003Cspan class=\"hljs-variable constant_\">CASE\u003C\u002Fspan> \u003Cspan class=\"hljs-variable constant_\">WHEN\u003C\u002Fspan> {\u003Cspan class=\"hljs-title class_\">Company\u003C\u002Fspan>} = \u003Cspan class=\"hljs-string\">''\u003C\u002Fspan> \u003Cspan class=\"hljs-variable constant_\">THEN\u003C\u002Fspan> \u003Cspan class=\"hljs-string\">'全社'\u003C\u002Fspan> \u003Cspan class=\"hljs-variable constant_\">ELSE\u003C\u002Fspan> {\u003Cspan class=\"hljs-title class_\">Company\u003C\u002Fspan>} \u003Cspan class=\"hljs-variable constant_\">END\u003C\u002Fspan>, \u003Cspan class=\"hljs-string\">'で、'\u003C\u002Fspan>,\n    \u003Cspan class=\"hljs-string\">'対象の支払い方法は'\u003C\u002Fspan>, \u003Cspan class=\"hljs-variable constant_\">CASE\u003C\u002Fspan> \u003Cspan class=\"hljs-variable constant_\">WHEN\u003C\u002Fspan> {\u003Cspan class=\"hljs-title class_\">PaymentType\u003C\u002Fspan>} = \u003Cspan class=\"hljs-string\">''\u003C\u002Fspan> \u003Cspan class=\"hljs-variable constant_\">THEN\u003C\u002Fspan> \u003Cspan class=\"hljs-string\">'全て'\u003C\u002Fspan> \u003Cspan class=\"hljs-variable constant_\">ELSE\u003C\u002Fspan> {\u003Cspan class=\"hljs-title class_\">PaymentType\u003C\u002Fspan>} \u003Cspan class=\"hljs-variable constant_\">END\u003C\u002Fspan>, \u003Cspan class=\"hljs-string\">'です。'\u003C\u002Fspan>,\n    \u003Cspan class=\"hljs-string\">'インプットデータ: '\u003C\u002Fspan>, all_json\n  ) \u003Cspan class=\"hljs-variable constant_\">AS\u003C\u002Fspan> prompt\n\u003Cspan class=\"hljs-variable constant_\">FROM\u003C\u002Fspan>\n  配列化した\u003Cspan class=\"hljs-title class_\">JSON\u003C\u002Fspan>データ\u003C\u002Fcode>\u003C\u002Fpre>\u003C\u002Fp>\u003C\u002Fblockquote>\u003Cp>④AIモデルを呼び出す\u003C\u002Fp>\u003Cblockquote>\u003Cp>\u003Cpre>\u003Ccode class=\"hljs\">\u003Cspan class=\"hljs-keyword\">SELECT\u003C\u002Fspan>\n  ml_generate_text_llm_result \u003Cspan class=\"hljs-keyword\">AS\u003C\u002Fspan> output\n\u003Cspan class=\"hljs-keyword\">FROM\u003C\u002Fspan>\n  ML.GENERATE_TEXT(\n    MODEL `codatum\u003Cspan class=\"hljs-operator\">-\u003C\u002Fspan>example.example.vertex_ai`,\n    (\u003Cspan class=\"hljs-keyword\">SELECT\u003C\u002Fspan> prompt \u003Cspan class=\"hljs-keyword\">FROM\u003C\u002Fspan> プロンプト),\n    STRUCT(\n      \u003Cspan class=\"hljs-number\">0.3\u003C\u002Fspan> \u003Cspan class=\"hljs-keyword\">AS\u003C\u002Fspan> temperature,\n      \u003Cspan class=\"hljs-number\">1000\u003C\u002Fspan> \u003Cspan class=\"hljs-keyword\">AS\u003C\u002Fspan> max_output_tokens,\n      \u003Cspan class=\"hljs-literal\">TRUE\u003C\u002Fspan> \u003Cspan class=\"hljs-keyword\">AS\u003C\u002Fspan> flatten_json_output\n    )\n  )\u003C\u002Fcode>\u003C\u002Fpre>\u003C\u002Fp>\u003C\u002Fblockquote>\u003Cp>プロンプトの書き方次第で、生成されるサマリーの安定度は大きく変わります。\u003C\u002Fp>\u003Cp>何を説明してほしいか、どの粒度で書いてほしいかを具体的に指定するほど、毎回のブレが小さくなります。\u003C\u002Fp>\u003Cp>\u003C\u002Fp>\u003Ch3>\u003Cb>テキストパネルチャートの追加\u003C\u002Fb>\u003C\u002Fh3>\u003Cfigure class=\"EmbeddedContent_Wrapper\">\u003Cimg src=\"https:\u002F\u002Fimages.ctfassets.net\u002Fggtw2zqmifs5\u002F5ddOKkkTCDlKxwdF1f3lbp\u002F0e5ff22b9fb34e878166cba0bd342b02\u002F2d507cab-99be-4986-acb7-1fc621019e8b.png\" alt=\"スクリーンショット 2026-08-14 11.32.09\">\u003C\u002Ffigure>\u003Cp>最後に、チャートタイプの選択画面から「テキストパネル」を選び、生成結果を表示するブロックとして追加します。\u003C\u002Fp>\u003Cp>テキストパネルは1行目の値を表示する仕様のため、複数のテキストデータが存在する場合は、そのうち1件しか表示されません。生成結果は1行に集約した状態で渡すようにしてください。\u003C\u002Fp>\u003Cp>\u003C\u002Fp>\u003Ch2>\u003Cb>運用時の注意点\u003C\u002Fb>\u003C\u002Fh2>\u003Cp>AIが生成したMarkdownが、コードブロックなどで全体を囲われた状態になっていると、テキストパネル側で正しく展開できません。\u003C\u002Fp>\u003Cp>プロンプトの中で「Markdown全体を囲う必要はない」旨を明示し、AIの出力がそのままMarkdownとして展開される形にしておく必要があります。\u003C\u002Fp>\u003Cp>\u003C\u002Fp>\u003Ch2>\u003Cb>まとめ\u003C\u002Fb>\u003C\u002Fh2>\u003Cp>人が書くテキストサマリーは、ユーザーのパラメータ操作や、更新されたデータにリアルタイムについてくることができないため、グラフとテキストの間にズレを生みやすいというデメリットがあります。\u003C\u002Fp>\u003Cp>BigQuery経由でVertex AIを呼び出し、集計結果をその場でサマリーに変換してテキストパネルに表示する形にすると、ユーザーがパラメータを変えるたびに、その時点のデータに合ったサマリーが自動的に生成されます。\u003C\u002Fp>\u003Cp>BigQuery以外のコネクションでも、AI関連の機能に対応していれば同じ構成で実現できます。\u003C\u002Fp>\u003Cp>まずは自社のデータで、集計・JSON変換・生成・表示という4つのステップを組んでみてください！\u003C\u002Fp>\u003Cp>\u003C\u002Fp>","Codatum Team",{"title":10,"slug":11,"description":12},"プロダクト","product","","https:\u002F\u002Fimages.ctfassets.net\u002Fggtw2zqmifs5\u002FzxchiVufvPmqAxfjuJegf\u002F3db0b8682c1396b1f143b0dbb0555441\u002FAIsummary.png","https:\u002F\u002Fimages.ctfassets.net\u002Fggtw2zqmifs5\u002F778TjlfJwyTXTLfNcYR5TL\u002F69df14e9ad66c6d013d4d3a76472947a\u002FAIsummary_og.png","2026-08-31T06:59:14.012Z","2026-08-31T07:55:15.186Z","2026-08-31T00:00+09:00","ja",[20,30,40],{"title":21,"slug":22,"description":23,"author":8,"category":24,"coverImageUrl":25,"ogImageUrl":26,"createdAt":27,"updatedAt":28,"datePublished":29,"locale":18},"AIエージェントのためのデータ分析環境: Codatum CLIをリリースしました！","codatum-cli-beta","手で組むBIから、AIが書くBIへ。Codatum CLIは、普段使っているAIエージェントから、Markdownでダッシュボードやレポートを作成し、リンクで共有・再実行できるデータ分析環境です。",{"title":10,"slug":11,"description":12},"https:\u002F\u002Fimages.ctfassets.net\u002Fggtw2zqmifs5\u002F6CmBdMv8pMgTsssSvs51sd\u002Fe5fd485d4a60cc44bb81045e08c1e65f\u002Fcover.png","https:\u002F\u002Fimages.ctfassets.net\u002Fggtw2zqmifs5\u002F3RlKGmndYGxO9Wvm3cR5NX\u002F998545ae2163a9995f209b978b913bc6\u002Fog.png","2026-08-03T21:00:11.196Z","2026-08-04T06:51:38.872Z","2026-08-04T06:00+09:00",{"title":31,"slug":32,"description":33,"author":34,"category":35,"coverImageUrl":36,"ogImageUrl":37,"createdAt":38,"updatedAt":38,"datePublished":39,"locale":18},"SQLは動くのに、なぜ分析は間違うのか","ai-data-analysis-38-percent","AI にデータ分析を任せても、SQL が動くことと分析が正しいことは別です。Data Agent Benchmark（DAB）で最新モデルでも pass@1（1 回で正解できた割合）が 38% にとどまった理由を、失敗の 85% を占める計画と実装の問題から読み解き、人間がレビューできる Data Agent の設計を考えます。","Naoki Shibayama",{"title":10,"slug":11,"description":12},"https:\u002F\u002Fimages.ctfassets.net\u002Fggtw2zqmifs5\u002F2RLeBK16dSIUNOf0leYv6h\u002F054743575aa7bba8f33a8c2df25a9070\u002Fcover-banner.png","https:\u002F\u002Fimages.ctfassets.net\u002Fggtw2zqmifs5\u002F3b9n82XQDour4myn1ZcYb\u002F9a0ff84d6a860c4456687a12ee2a6167\u002Fcover-hero.png","2026-06-22T01:00:10.416Z","2026-06-22T10:00:00+09:00",{"title":41,"slug":42,"description":43,"author":8,"category":44,"urlCategorySlug":11,"coverImageUrl":45,"ogImageUrl":46,"createdAt":47,"updatedAt":48,"datePublished":49,"locale":18},"署名付き埋め込みとは：セキュアなデータ提供を実現する組み込み型BI","embedded-analytics","顧客へのデータ提供を検討する上で、セキュリティと運用効率の両立、または開発・保守の工数に頭を悩ませている担当者は多いのではないでしょうか。 自社サービスにデータ分析機能やダッシュボードを組み込む方法の一つとして、「署名付き埋め込み（Embedded Analytics）」があります。署名付き埋め込みは、上記の課題を解決しながら、シームレスな顧客体験を提供することが可能です。 本記事では、署名付き埋め込み機能の仕組み、メリット・デメリット、実装ステップなどについて解説します。",{"title":10,"slug":11,"description":12},"https:\u002F\u002Fimages.ctfassets.net\u002Fggtw2zqmifs5\u002F2sxhcmyojbFe3WifesBP49\u002Ff470c652f865848aaa4687604c0a356d\u002Fcover.png","https:\u002F\u002Fimages.ctfassets.net\u002Fggtw2zqmifs5\u002F3dKwZPYOx3hNp9yLJ3iXaf\u002Ff5a3833843a685dbdbae870c16807d58\u002Fog.png","2025-11-19T09:36:01.589Z","2026-05-07T09:25:49.084Z","2025-11-19T00:00+09:00"]