Snowflake AI_COMPLETE関数入門|SQLでLLMを呼び出す方法・構造化出力・コスト管理まで解説

SnowflakeのAI_COMPLETE関数の概要を示すアイキャッチ図解。SQLからLLMを呼び出す基本構文、構造化出力の指定方法、トークン消費に基づくコスト管理のポイントを一枚にまとめた入門向けビジュアル Snowflake
この記事をシェアする𝕏B!FacebookLINEPocket

はじめに:SQLだけでLLMを呼び出せるAI_COMPLETE

Snowflakeの AI_COMPLETE は、SQLからLLMを呼び出して文章生成、要約、分類、抽出などを実行できるCortex AI関数です。以前は SNOWFLAKE.CORTEX.COMPLETE を使う例も多くありましたが、Snowflake公式では AI_COMPLETECOMPLETE の更新版として案内されています。これから新しく実装する場合は、AI_COMPLETE を中心に覚えるのがおすすめです。

本記事では、初心者の方に向けて、最小例から構造化出力・エラー詳細・コスト管理・権限・専用関数との使い分けまで、実務で必要な範囲を整理します。Cortex全体の位置づけはSnowflake Cortex入門もあわせてご覧ください。

AI_COMPLETEとは?

AI_COMPLETE は、プロンプト(指示文)とモデル名を渡すと、LLMによる生成結果を返すCortex AI関数です。SQLの関数として呼び出せるため、外部APIキーやSDKを準備しなくても、Snowflake内のデータと直接組み合わせて使えます。

  • 文章生成、要約、分類、抽出など幅広い用途に使える
  • テーブル列を || 演算子で連結してプロンプトに渡せる
  • 構造化出力(response_format)、トークン詳細(show_details)、エラー詳細(return_error_details)などのオプションがある
  • Snowflakeのロール・行レベルセキュリティ・マスキングがそのまま効く

旧SNOWFLAKE.CORTEX.COMPLETEとの違い

SNOWFLAKE.CORTEX.COMPLETE は既存SQLや過去記事で見かけることがあります。公式では AI_COMPLETE が更新版として案内されているため、最新機能を使う場合や新規実装では AI_COMPLETE を使うのがおすすめです。既存SQLを保守する場合は、旧 COMPLETE の仕様も確認しておきましょう。

比較項目AI_COMPLETESNOWFLAKE.CORTEX.COMPLETE
位置づけ現在のAI関数旧Cortex関数として既存SQLで見かけることがある
新規実装推奨基本的にはAI_COMPLETEへ寄せる
入力テキスト、画像、Prompt objectなどテキスト、会話形式、画像対応のバリエーションあり
構造化出力response_formatで指定可能旧形式の仕様を確認
エラー詳細return_error_detailsが利用可能仕様差分を確認
使い分け新しく書くSQL既存SQLの保守・読み替え

非推奨化の正確な期限など、公式で明確にされていない情報は本記事では断定しません。最新の状態はSnowflake公式ドキュメントで確認してください。

いちばんシンプルなAI_COMPLETEの使い方

まずは1つのプロンプトをLLMに渡すだけの最小例です。モデル名とプロンプトの2つを指定します。

SELECT AI_COMPLETE(
  'mistral-large2',
  'Snowflakeを3行で初心者向けに紹介してください。'
) AS answer;

戻り値は文字列です。検証段階では、まずこの形で「ちゃんと動くか」「出力イメージはどうか」を確認するのがおすすめです。

テーブル列と組み合わせる

実務では、テーブル列の値をプロンプトに組み込んで使うのが基本パターンです。レビュー文を要約する例を見てみましょう。

SELECT
  review_id,
  AI_COMPLETE(
    model => 'mistral-large2',
    prompt => '次のレビューを30文字以内で要約してください。レビュー: ' || review_text
  ) AS summary
FROM customer_reviews
WHERE review_text IS NOT NULL
LIMIT 10;
  • LIMIT を付けて少量で検証する
  • WHERE 条件で対象を絞る
  • 本番実行前に件数・文字数・トークン数を見積もる
  • 同じ行に何度も実行すると、そのたびにコストが発生する

プロンプトを作るときのコツ

AI_COMPLETEで安定した結果を得るには、プロンプトの書き方がとても大切です。

  • 何をしてほしいかを最初に書く
  • 出力形式を明確にする(箇条書き、JSON、1文だけなど)
  • 文字数や箇条書き数を指定する
  • 入力データと指示文を「レビュー:」「問い合わせ:」などのラベルで区切る
  • 重要な分類や抽出では、選択肢を明示する
  • 機密情報や個人情報をむやみに渡さない

問い合わせを4カテゴリに分類する例:

SELECT AI_COMPLETE(
  model => 'mistral-large2',
  prompt => '次の問い合わせを「配送」「返品」「請求」「その他」のいずれかに分類してください。回答はカテゴリ名だけにしてください。問い合わせ: ' || inquiry_text,
  model_parameters => {'temperature': 0, 'max_tokens': 20}
) AS category
FROM inquiries
LIMIT 10;

model_parametersで応答をコントロールする

model_parameters を使うと、出力のランダム性や最大トークン数などを細かく調整できます。

パラメータ役割使い方の目安
temperature出力のランダム性要約・分類は低め、アイデア出しは高め
top_p出力候補の多様性通常はtemperatureとどちらかを調整
max_tokens最大出力トークン数長すぎる回答を防ぐ。小さすぎると切れる
guardrailsCortex Guardで有害応答をフィルタ外部向け・社内展開時に検討
SELECT AI_COMPLETE(
  model => 'mistral-large2',
  prompt => 'Snowflakeのウェアハウスとは何か、初心者向けに説明してください。',
  model_parameters => {
    'temperature': 0.2,
    'max_tokens': 200,
    'guardrails': true
  }
) AS answer;
  • temperature を0に近づけると回答が安定しやすくなります。
  • max_tokens が小さすぎると途中で切れることがあります。
  • guardrails 利用時はCortex Guard分の追加コストが発生する場合があります。
  • 重要用途ではAI出力を人手で確認するフローを入れましょう。

show_detailsでトークン使用量を確認する

show_details => TRUE を指定すると、回答だけでなく、モデル名や使用トークン数などの詳細情報を含むOBJECTが返ります。コスト感をつかむために、検証段階では show_details を使うと便利です。

SELECT AI_COMPLETE(
  model => 'mistral-large2',
  prompt => 'Snowflakeを3行で説明してください。',
  model_parameters => {'max_tokens': 100},
  show_details => TRUE
) AS result;

トークン数を取り出して列にする例:

WITH result AS (
  SELECT AI_COMPLETE(
    model => 'mistral-large2',
    prompt => 'Snowflakeを3行で説明してください。',
    show_details => TRUE
  ) AS res
)
SELECT
  res:choices[0]:messages::string AS answer,
  res:usage:prompt_tokens::number AS prompt_tokens,
  res:usage:completion_tokens::number AS completion_tokens,
  res:usage:total_tokens::number AS total_tokens
FROM result;

response_formatで構造化出力を返す

response_format を指定すると、文字列ではなく構造化されたOBJECTで結果を取り出せます。後続SQLで列に展開しやすくなり、AIを使った分類・抽出パイプラインを組みやすくなります。

戻り値の形は、response_formatshow_details の組み合わせで変わります。

指定戻り値の主な形用途
response_format なし、show_details なし文字列単純な回答生成
response_format なし、show_details => TRUEchoices / usage を含むOBJECTトークン数確認
response_format あり、show_details なし指定した構造のOBJECT後続SQLで処理
response_format あり、show_details => TRUEstructured_output / usage を含むOBJECT構造化出力とトークン数を同時確認

TYPE OBJECT でフィールドを定義する書き方が、SQLとしてはいちばん読みやすくおすすめです。

SELECT AI_COMPLETE(
  model => 'mistral-large2',
  prompt => '次の問い合わせを分類してください。内容: 商品が届かないので配送状況を確認したいです。',
  model_parameters => {
    'temperature': 0,
    'max_tokens': 500
  },
  response_format => TYPE OBJECT(
    category STRING,
    urgency STRING,
    summary STRING
  )
) AS result;

JSON Schemaでより厳密に構造化する

より厳密に出力形式を指定したい場合は、response_format にJSON Schemaを渡せます。フィールドの型、必須項目、追加プロパティ可否などを細かく制御できます。

SELECT AI_COMPLETE(
  model => 'mistral-large2',
  prompt => '次の問い合わせを分類してください。内容: 商品が届かないので配送状況を確認したいです。',
  model_parameters => {
    'temperature': 0,
    'max_tokens': 500
  },
  response_format => {
    'type': 'json',
    'schema': {
      'type': 'object',
      'properties': {
        'category': {'type': 'string'},
        'urgency': {'type': 'string'},
        'summary': {'type': 'string'}
      },
      'required': ['category', 'urgency', 'summary'],
      'additionalProperties': false
    }
  }
) AS result;
  • JSON Schemaを使うと、より厳密に出力形式を指定できます。
  • OpenAI系モデルでは、すべてのプロパティを required に含め、各ノードで additionalProperties: false が必要になる場合があります。
  • 仕様は変わる可能性があるため、最新の公式ドキュメントを確認してください。

show_details => TRUEresponse_format を同時に使うと、構造化出力に加えてトークン使用量も同時に取れます。

SELECT AI_COMPLETE(
  model => 'mistral-large2',
  prompt => '次の問い合わせを分類してください。内容: 商品が届かないので配送状況を確認したいです。',
  response_format => TYPE OBJECT(
    category STRING,
    urgency STRING,
    summary STRING
  ),
  show_details => TRUE
) AS result;

この場合、通常の choices ではなく、structured_outputusage を含むOBJECTが返ります。構造化結果は result:structured_output、トークン数は result:usage:total_tokens などで取り出せます。

return_error_detailsでエラー詳細を確認する

通常、処理できない入力ではNULLが返ることがあります。複数行クエリでは一部の行が失敗しても、クエリ全体が止まらない場合もあるため、本番でエラー行だけを再処理できる仕組みがあると安心です。return_error_details => TRUE を指定すると、成功時は value、失敗時は error を含むOBJECTが返ります。

SELECT AI_COMPLETE(
  model => 'mistral-large2',
  prompt => 'Snowflakeを1文で説明してください。',
  return_error_details => TRUE
) AS result;
  • 通常、処理できない入力ではNULLが返ります。
  • 複数行クエリでは一部の行が失敗しても、クエリ全体が止まらない場合があります。
  • return_error_details => TRUE を指定すると、成功時は value、失敗時は error を確認できます。
  • 本番ではエラー行だけを再処理できる設計にしておきましょう。

生成結果をテーブルに保存する

毎回AI関数を再実行するとコストが増えていきます。一度生成した結果はテーブルに保存し、後続クエリではそれを参照するのがおすすめです。

CREATE OR REPLACE TABLE customer_reviews_ai_summary AS
SELECT
  review_id,
  review_text,
  AI_COMPLETE(
    model => 'mistral-large2',
    prompt => '次のレビューを30文字以内で要約してください。レビュー: ' || review_text
  ) AS summary,
  CURRENT_TIMESTAMP() AS generated_at
FROM customer_reviews
WHERE review_text IS NOT NULL
LIMIT 10;
  • 毎回AI関数を再実行するとコストが増えます。
  • 一度生成した結果はテーブルに保存して使い回します。
  • 更新日時やIDを使って、新規・変更分だけ再生成する設計にします。
  • 本番では一時テーブルではなく、履歴管理できる正規のテーブルを検討します。

差分処理で再実行コストを抑える

未処理の行だけを対象にすれば、同じ行に対する重複実行を避けられます。次のSQLは「既存サマリテーブルに無いレビューだけを処理する」概念例です。

CREATE OR REPLACE TABLE customer_reviews_ai_summary AS
SELECT
  r.review_id,
  r.review_text,
  AI_COMPLETE(
    model => 'mistral-large2',
    prompt => '次のレビューを30文字以内で要約してください。レビュー: ' || r.review_text
  ) AS summary,
  CURRENT_TIMESTAMP() AS generated_at
FROM customer_reviews r
LEFT JOIN customer_reviews_ai_summary s
  ON r.review_id = s.review_id
WHERE r.review_text IS NOT NULL
  AND s.review_id IS NULL
LIMIT 100;

注意:上記は概念例です。実務では INSERT INTOMERGE を使って、既存テーブルを上書きしない設計にしてください。Streamsや更新日時カラムと組み合わせると、増分処理をきれいに設計できます。

AI_COMPLETEを使うための権限

AI_COMPLETEを使うには、利用ロールにAI関数の利用権限と、必要なデータベースロールが必要です。検証環境では広めの権限、本番環境では必要な関数だけに絞る設計を検討します。

検証用ロール例(AI関数全体を許可):

USE ROLE ACCOUNTADMIN;

CREATE ROLE IF NOT EXISTS ai_user_role;

GRANT USE AI FUNCTIONS ON ACCOUNT TO ROLE ai_user_role;
GRANT DATABASE ROLE SNOWFLAKE.AI_FUNCTIONS_USER TO ROLE ai_user_role;

GRANT ROLE ai_user_role TO USER <USER_NAME>;

個別関数だけ許可する例(AI_COMPLETEのみ):

USE ROLE ACCOUNTADMIN;

CREATE ROLE IF NOT EXISTS ai_complete_user_role;

GRANT USE AI FUNCTION AI_COMPLETE
  ON ACCOUNT TO ROLE ai_complete_user_role;

GRANT DATABASE ROLE SNOWFLAKE.AI_FUNCTIONS_USER
  TO ROLE ai_complete_user_role;

GRANT ROLE ai_complete_user_role TO USER <USER_NAME>;
  • USE AI FUNCTIONS はAI関数全体を許可する権限です。
  • USE AI FUNCTION AI_COMPLETE はAI_COMPLETEだけを許可する個別権限です。
  • SNOWFLAKE.CORTEX_USER または SNOWFLAKE.AI_FUNCTIONS_USER のデータベースロールが必要になる場合があります。
  • 本番では必要な関数だけに絞ります。
  • PUBLIC に広く付与しすぎないようにしてください。

コスト・トークン・ウェアハウスの考え方

  • AI_COMPLETEは入力トークンと出力トークンの両方がコストに影響します。
  • show_details で実行後のトークン数を確認できます。
  • AI_COUNT_TOKENS は事前見積もりに使えますが、実際の課金トークン数と完全一致しない場合があります。
  • guardrails 利用時はCortex Guard分の追加コストが発生する場合があります。
  • AI関数を呼び出すクエリでは、通常のウェアハウス稼働コストも発生します。
  • 大きすぎるウェアハウスを使ってもAI関数自体の処理が速くなるとは限りません。
  • まずは LIMIT 10 で少量検証してから本番投入します。
  • 実行結果はテーブルに保存し、同じ行を何度も再実行しないようにします。

料金体系の全体像はSnowflakeの料金体系をやさしく解説、急な増加への対処はSnowflakeのクレジット急増の原因調査と削減方法もご覧ください。

使用量を確認するSQL

Cortex AI関数の利用量は、Account Usageの専用ビューで確認できます。まずは列構成を DESC VIEW で確認してから集計するのがおすすめです。

DESC VIEW SNOWFLAKE.ACCOUNT_USAGE.CORTEX_AI_FUNCTIONS_USAGE_HISTORY;

日別・関数別・モデル別のクレジット消費:

SELECT
  DATE_TRUNC('day', START_TIME) AS usage_date,
  FUNCTION_NAME,
  MODEL_NAME,
  SUM(CREDITS) AS total_credits,
  COUNT(DISTINCT QUERY_ID) AS query_count
FROM SNOWFLAKE.ACCOUNT_USAGE.CORTEX_AI_FUNCTIONS_USAGE_HISTORY
WHERE START_TIME >= DATEADD('day', -30, CURRENT_TIMESTAMP())
GROUP BY 1, 2, 3
ORDER BY usage_date DESC, total_credits DESC;

ユーザー別のクレジット消費(直近3か月):

SELECT
  DATE_TRUNC('month', h.START_TIME) AS usage_month,
  u.NAME AS user_name,
  u.EMAIL,
  u.DEFAULT_ROLE,
  SUM(h.CREDITS) AS total_credits,
  COUNT(DISTINCT h.QUERY_ID) AS query_count
FROM SNOWFLAKE.ACCOUNT_USAGE.CORTEX_AI_FUNCTIONS_USAGE_HISTORY h
JOIN SNOWFLAKE.ACCOUNT_USAGE.USERS u
  ON h.USER_ID = u.USER_ID
WHERE h.START_TIME >= DATEADD('month', -3, CURRENT_TIMESTAMP())
GROUP BY 1, 2, 3, 4
ORDER BY usage_month DESC, total_credits DESC;
  • CORTEX_AI_FUNCTIONS_USAGE_HISTORY はCortex AI関数の使用状況確認に使います。
  • ビューの列名や利用可否はSnowflakeの仕様変更で変わる可能性があります。
  • 古い記事や環境では CORTEX_FUNCTIONS_USAGE_HISTORY などのビュー名を見かける場合があるため、最新の公式ドキュメントで確認してください。

AI_COMPLETEに向いている用途・注意が必要な用途

向いている用途

  • 問い合わせ文の要約
  • レビューの要約・分類
  • メール文面の下書き
  • SQLコメントやドキュメント文の生成
  • ログや障害メモの一次整理
  • 多言語テキストの下訳・要約
  • ルールベースでは書きにくいテキスト処理

注意が必要な用途

  • 法務・医療・金融など高リスク文書の最終判断
  • 正確性が必須の確定処理
  • 個人情報や機密情報を含むテキストの無制限投入
  • 大量行への無検証実行
  • AI出力をそのまま顧客へ返す処理

専用AI関数との使い分け

AI_COMPLETE は汎用的で便利ですが、翻訳・感情分析・分類・構造化抽出などは専用関数の方がシンプルで読みやすいSQLになる場合があります。何でも AI_COMPLETE で処理するのではなく、用途に合う専用関数があるか確認しましょう。

やりたいこと優先候補
自由文生成・柔軟な指示AI_COMPLETE
複数行の要約AI_SUMMARIZE_AGG
複数行から洞察を出すAI_AGG
翻訳AI_TRANSLATE
感情分析AI_SENTIMENT
分類AI_CLASSIFY
構造化抽出AI_EXTRACT
PIIマスキングAI_REDACT

各関数の詳細は、Snowflake Cortex AI関数まとめAI_TRANSLATE入門AI_EXTRACT入門SUMMARIZE / AI_SUMMARIZE_AGG入門も参考にしてください。

よくあるエラーと確認ポイント

症状確認ポイント
権限エラーになるUSE AI FUNCTIONS または USE AI FUNCTION AI_COMPLETEAI_FUNCTIONS_USER / CORTEX_USER を確認
NULLが返る入力が長すぎる、未対応形式、モデル・リージョン制限、エラー詳細を確認
出力が途中で切れるmax_tokens が小さすぎないか
JSONが崩れるresponse_format を使う。JSON Schemaを見直す
コストが増えるLIMIT、WHERE、対象件数、出力長、モデル、Usage Historyを確認
結果が安定しないtemperature を下げる、選択肢を明示する
不適切な出力が出るguardrails、プロンプト改善、人手確認を検討

コスト超過を防ぐ仕組みはSnowflake Resource Monitor入門も参考になります。

まとめ

Snowflakeの AI_COMPLETE を使えば、SQLからLLMを呼び出して文章生成、要約、分類、抽出などをSnowflake上のデータ処理に組み込めます。新規実装では、旧 SNOWFLAKE.CORTEX.COMPLETE ではなく AI_COMPLETE を中心に使うのがおすすめです。実務利用では、model_parametersshow_detailsresponse_formatreturn_error_details を使い分け、結果をテーブルに保存して再実行コストを抑えましょう。さらに、Usage Historyでコストを確認し、用途によっては AI_TRANSLATEAI_SENTIMENTAI_EXTRACT などの専用関数も検討すると、より安全で読みやすいSQLになります。

参考リンク

※リンク先のパスはSnowflake側の構成変更で変わる可能性があります。最新URLは公式ドキュメントのトップから検索してください。

関連記事

この記事をシェアする𝕏B!FacebookLINEPocket