🖼️

画像から楽に構造化データを抽出したい

に公開

本記事は Snowflake Advent Calendar 2025 の3日目の記事です。


はじめに

みなさん、こんな経験ありませんか?

  • 取引先から届いた 画像データ
  • 社内の誰かが スマホで撮った写真
  • ネットで拾ってきた 画像データ

「この画像の中身、楽に簡単に構造化データにしたいな…」
と感じたことがある方、きっといるはずです。

私も、実業務で多数ある画像からデータを抽出して、グラフ化するシーンに出会い、
Snowflake の AI 機能で実施したので、その際の対応方法について、紹介していきます!


お断り

今回、記事を書く上で、サンプル画像を生成AIに作成してもらおうと思ったのですが、良い感じに生成できず、生成AIで簡単に作成できた架空の請求書画像を使っていきます。

請求書は、画像形式ではなく、普通PDFでしょ。とツッコミがあるとは思いますが、PDFを写真で撮影したようなケースや、こんな画像があったらと想像して、読んでもらえたらと思います。

また、請求書データを構造化データにするにあたり、テーブル項目や正規化はサンプルという温かい気持ちで読んでいただければと!


今回の記事でやること

Snowflake の AI 機能である

  • AI_COMPLETE
  • AI_EXTRACT

の2つの方法で、画像 → 構造化データの抽出を試します。

また、AI機能は再現性の問題や100%正しく抽出できる訳ではないので、ヒトの目で確認して、加筆修正できるように、以下機能を持つStreamlitアプリを作成していきます。

  • 画像をアップロード
  • AIでの抽出結果を表示
  • 抽出結果は編集可能にする
  • ヒトの確認・修正結果をテーブルに登録

▼ 非構造化データから構造化データを抽出する機能について、以下記事が参考になります
Snowflakeにおける非構造化データを構造化データに変える選択肢

AI_PARSE_DOCUMENT
文書全体を抽出する機能であり、その後JSONをこねくり回し、必要項目のみに抽出する必要があり、
本シナリオでは、手間もかかり使われることはないと思うので、割愛します。


今回のサンプル画像

生成AIで、架空の会社と架空の請求内容を作ってもらいました。


抽出する構造化データ

画像から以下2つのデータを抽出していきます。

  • 単一行のデータとなる請求書テーブル
  • 複数行になる請求書詳細テーブル

▼請求書テーブル

CREATE OR REPLACE TABLE Invoices (
    invoice_date DATE COMMENT '日付',
    invoice_number STRING COMMENT '請求書番号',
    client_company STRING COMMENT '請求先会社名',
    client_postcode STRING COMMENT '請求先郵便番号',
    client_address STRING COMMENT '請求先住所',
    client_contact STRING COMMENT '請求先担当者氏名',
    client_phone STRING COMMENT '請求先電話番号',
    subtotal NUMBER COMMENT '小計',
    tax NUMBER COMMENT '消費税',
    total NUMBER COMMENT '合計'
);

▼請求書詳細テーブル

CREATE OR REPLACE TABLE Invoice_Details (
    invoice_number STRING COMMENT '請求書番号',
    quantity NUMBER COMMENT '数量',
    description STRING COMMENT '内容',
    unit_price NUMBER COMMENT '単価',
    amount NUMBER COMMENT '金額'
);

Snowflakeで実際に抽出してみた

AI_COMPLETE を使う場合

上述参考サイトで記載のないAI_COMPLETE関数について、触れていきます。

AI_COMPLETEは汎用的な関数で、画像モーダルでは、ChatGPT などでファイルを添付して、プロンプトで指示すると同じような動きのイメージとなります。
(尚、執筆時点では、AI_COMPLETE関数はPDFには対応していないです。)

以下SQLは、ChatGPT などに、事前に試したプロンプトをそのままにしています。
ChatGPT であれば、結果をそのままExcelにコピペできるような形式で出力してくれます。
ChatGPT で上記のやり方は、結構便利で、私はよく使っています。
尚、Snowflakeでその後扱うには、JSON形式での指定や備考などの余分なものは出力しないようにする必要があります。

▼SQL

SELECT
    AI_COMPLETE(
    'openai-gpt-4.1',
$$
画像に対し、抽出仕様に基づきテーブルデータ項目の形式で出力をお願いします。

#抽出仕様
- 請求書と請求書詳細の2つを出力してください。
- 入力テキストにノイズや改行の乱れがあっても補正して抽出してください。
- 電話番号の表記ゆれ(TEL / 電話番号 / TELなど)は適切に判定してください。
- 価格は数値として抽出してください。
- 文字を抽出する際、アルファベットや数字は半角、カタカナは全角にしてください
- 取引日時は、YYYY-MM-DDの形式で、Snowflakeで日時として取り込めるようにしてください。
- 電話番号は、XXXX-XX-XXXXのように、市外局番との境などは、-にしてください。
- 抽出できない項目および存在しない項目は null を設定してください。

#テーブルデータ項目(請求書)
・日付
・請求書番号
・請求先会社名
・請求先郵便番号
・請求先住所
・請求先担当者氏名
・請求先電話番号
・小計
・消費税
・合計

#テーブルデータ項目(請求書詳細)
・請求書番号
・数量
・内容
・単価
・金額
$$,
    TO_FILE('@SCAN_PICTURE','sample_invoice.jpg')
    );

▼取得結果

"以下、抽出仕様に基づきテーブルデータ項目形式で出力します。
日付 請求書番号 請求先会社名 請求先郵便番号 請求先住所 請求先担当者氏名 請求先電話番号 小計 消費税 合計
2025-12-02 NLS-INV-202512-0148 株式会社ブルースカイテクノロジーズ 160-8810 東京都新宿区西新宿4-18-9 ブルースカイビル7F 青空 技術 03-5789-2241 640000 64000 704000
請求書番号 数量 内容 単価 金額
NLS-INV-202512-0148 1 クラウド保守運用総合サポート 120000 120000
NLS-INV-202512-0148 2 サーバー監視設定作業 45000 90000
NLS-INV-202512-0148 3 データ移行作業 30000 90000
NLS-INV-202512-0148 1 API連携作業 85000 85000
NLS-INV-202512-0148 5 ドキュメント作成 8000 40000
NLS-INV-202512-0148 2 技術コンサルティング(2h) 12000 24000
NLS-INV-202512-0148 1 テスト環境セットアップ 55000 55000
NLS-INV-202512-0148 1 セキュリティ診断 98000 98000
NLS-INV-202512-0148 1 メールサポート(月額) 10000 10000
NLS-INV-202512-0148 1 バックアップ設定 28000 28000
抽出できない項目(例:請求先担当者氏名)は、記載されている「青空 技術」を設定しましたが、役職名等は不明のためnullとしています。
価格はカンマなしの数値で抽出しています。
電話番号は「TEL」「TEL」等の表記ゆれを正規化しています。
住所・会社名等は画像内の表記に準拠しています。
消費税は小計の10%(64000円)として算出しています。"

AI_EXTRACT を使う場合

▼請求書テーブルSQL

SELECT 
  ai_extract(
    file => TO_FILE('@SCAN_PICTURE', 'sample_invoice.jpg'),
    responseFormat => [
      ['日付', '請求書の日付はいつですか? YYYY-MM-DDの形式で、Snowflakeで日時として取り込めるようにしてください。'],
      ['請求書番号', '請求書番号は何ですか?'],
      ['請求先会社名', '請求先会社名は何ですか? 文字を回答する際、アルファベットや数字は半角、カタカナは全角にしてください'],
      ['請求先郵便番号', '請求先郵便番号は何ですか?'],
      ['請求先住所', '請求先住所は何ですか? 文字を回答する際、アルファベットや数字は半角、カタカナは全角にしてください'],
      ['請求先担当者', '宛先の氏名もしくは請求先担当者氏名は誰ですか?'],
      ['請求先電話番号', '請求先電話番号は何ですか?'],
      ['小計', '小計はいくらですか? 小数点は除去し整数の数値として回答してください。'],
      ['消費税', '消費税はいくらですか? 小数点は除去し整数の数値として回答してください。'],
      ['合計', '合計はいくらですか? 小数点は除去し整数の数値として回答してください。']
    ]
  );

▼請求書テーブル取得結果
プロンプトを色々変えて試しましたが、小計の小数点を整数として出力できなかったです。
また、請求先担当者が上手く抽出できなかった。(一番最初に試していたときは抽出できたのですが、、、)

{
  "error": null,
  "response": {
    "合計": "7040000",
    "小計": "6400000.00",
    "日付": "2025-12-02",
    "消費税": "1040000",
    "請求先会社名": "株式会社ブルースカイプロジェクト",
    "請求先住所": "〒160-8810 東京都新宿区西新宿4-18-9 ブルースカイビルD",
    "請求先担当者": "南空 悦朗",
    "請求先郵便番号": "160-8810",
    "請求先電話番号": "03-5789-2241",
    "請求書番号": "NLS-INV-202512-0148"
  }
}

▼請求書詳細テーブルSQL

SELECT ai_extract(
    file => TO_FILE('@SCAN_PICTURE', 'sample_invoice.jpg'),
    responseFormat => [
        ['明細_請求書番号', '明細の請求書番号を順に抽出してください'],
        ['明細_数量', '明細の数量を順に抽出してください。カンマや記号は削除してください'],
        ['明細_内容', '明細の内容を順に抽出してください'],
        ['明細_単価', '明細の単価を順に抽出してください。カンマや記号は削除してください'],
        ['明細_金額', '明細の金額を順に抽出してください。カンマや記号は削除してください']
    ]
);

▼請求書詳細テーブル取得結果

{
  "error": null,
  "response": {
    "明細_内容": [
      "クラウド環境構築サポート",
      "サーバー監視設定作業",
      "データ移行作業",
      "API連携実装",
      "ドキュメント作成",
      "技術コラボテイング(2h)",
      "テスト環境セットアップ",
      "セミナ参加割",
      "メールサポート(月額)",
      "バックアップ設定"
    ],
    "明細_単価": [
      "120,000",
      "45,000",
      "30,000",
      "85,000",
      "8,000",
      "12,000",
      "55,000",
      "98,000",
      "10,000",
      "28,000"
    ],
    "明細_数量": [
      "1",
      "2",
      "3",
      "1",
      "5",
      "2",
      "1",
      "1",
      "1",
      "1"
    ],
    "明細_請求書番号": "NLS-INV-202512-0148",
    "明細_金額": [
      "120,000",
      "90,000",
      "90,000",
      "85,000",
      "40,000",
      "24,000",
      "35,000",
      "98,000",
      "10,000",
      "28,000"
    ]
  }
}

Streamlit で画面UIを作ってみた

Streamlitのプログラム

ここからは、生成AIに画面仕様を伝えて、エラーや想定しない挙動に対して、修正コード作成のお願いしてStreamlitのアプリを作成しました。
不要なコードが残っているやスマートなコードでない等は、ご容赦ください。

コード
import streamlit as st
import snowflake.snowpark as snowpark
import pandas as pd
import tempfile
import os
import uuid  # ファイル名生成用
import json

# Snowflakeセッションを取得
session = snowpark.Session.builder.getOrCreate()

st.title("📊 画像からデータ抽出し、データ登録するアプリ")


# === 日本語 → 英語 のカラム名マッピング ===
invoices_columns = {
    "日付": "INVOICE_DATE",
    "請求書番号": "INVOICE_NUMBER",
    "請求先会社名": "CLIENT_COMPANY",
    "請求先郵便番号": "CLIENT_POSTCODE",
    "請求先住所": "CLIENT_ADDRESS",
    "請求先担当者氏名": "CLIENT_CONTACT",
    "請求先電話番号": "CLIENT_PHONE",
    "小計": "SUBTOTAL",
    "消費税": "TAX",
    "合計": "TOTAL"
}

invoice_Details_columns = {
    "請求書番号": "INVOICE_NUMBER",
    "数量": "QUANTITY",
    "内容": "DESCRIPTION",
    "単価": "UNIT_PRICE",
    "金額": "AMOUNT"
}

# 永続ステージ名
FULL_STAGE_NAME  = "@DB.SCM.SCAN_PICTURE"

# アップロードファイルをセッションに保持
if "uploaded_file" not in st.session_state:
    st.session_state.uploaded_file = None
    
# ファイルアップロード
uploaded_file = st.file_uploader(
    "📁画像をアップロードしてください",
    type=["png", "jpg", "jpeg"]
)

if uploaded_file:
    # アップロードファイルをセッションに保持
    st.session_state.uploaded_file = uploaded_file
    st.image(uploaded_file, caption="アップロード画像プレビュー", use_container_width=True)
    st.info("AIモデルで解析中...(数十秒かかる場合があります)")

    # Snowflake上で使うファイル名(小文字で統一)
    safe_file_name = f"upload_{uuid.uuid4().hex}.png"

    # 一時ファイルを Snowflake と同じ名前で保存
    tmp_dir = tempfile.mkdtemp()
    tmp_path = os.path.join(tmp_dir, safe_file_name)
    with open(tmp_path, "wb") as f:
        f.write(uploaded_file.getbuffer())
        
    # 内部ステージにファイルをアップロード
    put_results = session.file.put(tmp_path, FULL_STAGE_NAME, auto_compress=False, overwrite=True)

    # デバッグ用 ファイルアップロード結果の確認
    # st.write("📤 PUT結果:", put_results)

    listed_files = session.sql(f"LIST {FULL_STAGE_NAME}").collect()
    file_names = [row["name"] for row in listed_files]

    # デバッグ用 実際にアップロードされたファイル名をSnowflakeから確認
    # st.write("📂 現在ステージ内のファイル一覧:", file_names)

    # 実際にアップロードされたファイル名(.gz対策)
    matched_file = next((f for f in file_names if safe_file_name in f or safe_file_name + ".GZ" in f), None)

    if not matched_file:
        st.error("❌ ステージ上にファイルが見つかりません。PUT処理が成功しているか確認してください。")
        st.stop()

    # ステージ上のファイルパスを構築
    stage_file_path = f"{FULL_STAGE_NAME}/{os.path.basename(matched_file)}"

    # --- プロンプトを定義 ---
    prompt = """
画像に対し、抽出仕様に基づきテーブルデータ項目の形式で出力をお願いします。

#抽出仕様
- 請求書と請求書詳細の2つを出力してください。
- 入力テキストにノイズや改行の乱れがあっても補正して抽出してください。
- 電話番号の表記ゆれ(TEL / 電話番号 / TELなど)は適切に判定してください。
- 価格は数値として抽出してください。
- 文字を抽出する際、アルファベットや数字は半角、カタカナは全角にしてください。
- 取引日時は、YYYY-MM-DDの形式で、Snowflakeで日時として取り込めるようにしてください。
- 電話番号は、XXXX-XX-XXXXのように、市外局番との境などは、-にしてください。
- 抽出できない項目および存在しない項目は null を設定してください。

#テーブルデータ項目(請求書)
・日付
・請求書番号
・請求先会社名
・請求先郵便番号
・請求先住所
・請求先担当者氏名
・請求先電話番号
・小計
・消費税
・合計

#テーブルデータ項目(請求書詳細)
・請求書番号
・数量
・内容
・単価
・金額

出力は必ず次の構造のJSON形式で返してください。
{
    "Invoices": [請求書の各レコード],
    "Invoice_Details": [請求書詳細の各レコード]
}
出力はJSONのみを返し、説明文やマークダウン記号を含めないでください。
    """

    # --- AI_COMPLETEを実行(ステージパスを指定) ---
    query = f"""
    SELECT PARSE_JSON(
        AI_COMPLETE(
            'openai-gpt-4.1',
            $${prompt}$$,
            TO_FILE('{stage_file_path}')
        )
    ) AS RESULT_JSON
    """

    # デバッグ用 実行クエリ
    # st.code(query)

    # SnowflakeでAI_COMPLETEを実行
    try:
        result = session.sql(query).collect()[0]["RESULT_JSON"]
    except Exception as e:
        st.error(f"❌ Snowflake処理中にエラーが発生しました: {e}")
        st.stop()

    # --- JSONパースを強制的に実施 ---
    if isinstance(result, str):
        try:
            result = json.loads(result)
        except Exception as e:
            st.error(f"❌ JSONとして解析できません: {e}")
            st.stop()

    invoices = pd.DataFrame(result.get("Invoices", []))
    invoice_Details = pd.DataFrame(result.get("Invoice_Details", []))

    # カラム順序の定義
    invoice_columns_order = [
        "日付", "請求書番号", "請求先会社名", "請求先郵便番号", 
        "請求先住所", "請求先担当者氏名", "請求先電話番号",
        "小計", "消費税", "合計"
    ]

    invoice_details_columns_order = [
        "請求書番号", "数量", "内容", "単価", "金額"
    ]

    # --- DataFrame編集用に表示 ---
    st.subheader("📘 請求書(AI_COMPLETE)")
    edited_invoices = st.data_editor(
        invoices[invoice_columns_order], 
        num_rows="dynamic"
    )

    st.subheader("📗 請求書詳細(AI_COMPLETE)")
    edited_invoice_Details = st.data_editor(
        invoice_Details[invoice_details_columns_order], 
        num_rows="dynamic"
    )
    
    
    # --- 登録ボタン ---
    if st.button("💾 修正内容をデータとして保存"):

        # --- Invoices 登録 ---
        if not edited_invoices.empty:
            # 日本語 → 英語マッピング
            df_to_save = edited_invoices.rename(columns=invoices_columns)

            # DataFrameの列名を大文字に統一(Snowflakeテーブル列名と一致)
            df_to_save.columns = [c.upper() for c in df_to_save.columns]

            # デバッグ用
            #st.write("Invoices 登録前の列名:", df_to_save.columns.tolist())

            session.write_pandas(
                df_to_save,
                table_name="INVOICES",
                auto_create_table=False,
                overwrite=True
            )

        # --- Invoice_Details 登録 ---
        if not edited_invoice_Details.empty:
            df_to_save = edited_invoice_Details.rename(columns=invoice_Details_columns)
            df_to_save.columns = [c.upper() for c in df_to_save.columns]

            # デバッグ用
            #st.write("Invoice_Details 登録前の列名:", df_to_save.columns.tolist())

            session.write_pandas(
                df_to_save,
                table_name="INVOICE_DETAILS",
                auto_create_table=False,
                overwrite=True
            )

        st.success("✅ データ登録が完了しました")


    # -----------------------
    # AI_EXTRACT 部分
    # -----------------------
    st.divider()
    st.subheader("✨ AI_EXTRACT による抽出結果")

    # --- 請求書 ---
    extract_invoice_query = f"""
    SELECT ai_extract(
        file => TO_FILE('{stage_file_path}'),
        responseFormat => [
            ['日付', '請求書の日付はいつですか?'],
            ['請求書番号', '請求書番号は何ですか?'],
            ['請求先会社名', '請求先会社名は何ですか?'],
            ['請求先郵便番号', '請求先郵便番号は何ですか?'],
            ['請求先住所', '請求先住所は何ですか?'],
            ['請求先担当者氏名', '請求先担当者氏名は誰ですか?'],
            ['請求先電話番号', '請求先電話番号は何ですか?'],
            ['小計', '小計はいくらですか?'],
            ['消費税', '消費税はいくらですか?'],
            ['合計', '合計はいくらですか?']
        ]
    ) AS invoice_extract
    """

    try:
        invoice_result = session.sql(extract_invoice_query).collect()[0]["INVOICE_EXTRACT"]
        # JSON文字列ならパース
        if isinstance(invoice_result, str):
            invoice_result = json.loads(invoice_result)
    except Exception as e:
        st.error(f"❌ AI_EXTRACT 請求書処理中にエラー: {e}")
        st.stop()

    # レスポンス部分を取り出して DataFrame 化
    invoice_response = invoice_result.get("response", {})
    # 項目順に並べ替え
    invoice_columns = [
        "日付","請求書番号","請求先会社名","請求先郵便番号",
        "請求先住所","請求先担当者氏名","請求先電話番号",
        "小計","消費税","合計"
    ]
    df_extract_invoice = pd.DataFrame([invoice_response])[invoice_columns]

    st.subheader("📘 請求書(AI_EXTRACT)")
    st.dataframe(df_extract_invoice)

    # --- 請求書明細(列ごとに抽出) ---
    extract_details_query = f"""
    SELECT ai_extract(
        file => TO_FILE('{stage_file_path}'),
        responseFormat => [
            ['明細_請求書番号', '明細の請求書番号を順に抽出してください'],
            ['明細_数量', '明細の数量を順に抽出してください。カンマや記号は削除してください'],
            ['明細_内容', '明細の内容を順に抽出してください'],
            ['明細_単価', '明細の単価を順に抽出してください。カンマや記号は削除してください'],
            ['明細_金額', '明細の金額を順に抽出してください。カンマや記号は削除してください']
        ]
    ) AS details_extract
    """

    try:
        details_result = session.sql(extract_details_query).collect()[0]["DETAILS_EXTRACT"]
        if isinstance(details_result, str):
            details_result = json.loads(details_result)
    except Exception as e:
        st.error(f"❌ AI_EXTRACT 請求書明細処理中にエラー: {e}")
        st.stop()

    # 明細リストを DataFrame 化
    detail_keys = ["明細_請求書番号","明細_数量","明細_内容","明細_単価","明細_金額"]
    row_count = 0
    for k in detail_keys:
        v = details_result.get("response", {}).get(k, [])
        if isinstance(v, list):
            row_count = max(row_count, len(v))
    details_list = []
    for i in range(row_count):
        row = {}
        for k in detail_keys:
            v = details_result.get("response", {}).get(k, [])
            if isinstance(v, list):
                row[k] = v[i] if i < len(v) else None
            else:
                row[k] = v
        details_list.append(row)

    df_extract_details = pd.DataFrame(details_list)
    # カラム順を指定
    details_columns = ["明細_請求書番号","明細_数量","明細_内容","明細_単価","明細_金額"]
    df_extract_details = df_extract_details[details_columns]
    df_extract_details.rename(columns={
        "明細_請求書番号":"請求書番号",
        "明細_数量":"数量",
        "明細_内容":"内容",
        "明細_単価":"単価",
        "明細_金額":"金額"
    }, inplace=True)

    st.subheader("📗 請求書明細(AI_EXTRACT)")
    st.data_editor(df_extract_details, num_rows="dynamic")

    # --- 初期表示に戻るボタン ---
    if st.button("🔄 初期表示に戻る"):
        st.session_state.clear()
        st.rerun()

else:
    st.warning("画像ファイルをアップロードしてください。")

Streamlitの画面

<初期表示>

<画像アップロード後>


<データ修正>
請求先住所と請求書担当者氏名と合計が上手く読み込めてなかったので修正
▼修正前

▼修正後

<データ保存>


テーブル登録結果

今回は、AI_COMPLETEのほうのみ、テーブル登録するようにしています。
これで、順次画像データを取り込んでいけば、該当テーブルを参照しているBIツールのダッシュボードも自動で更新されていくようになります。

▼請求書テーブル

INVOICE_DATE INVOICE_NUMBER CLIENT_COMPANY CLIENT_POSTCODE CLIENT_ADDRESS CLIENT_CONTACT CLIENT_PHONE SUBTOTAL TAX TOTAL
2025-12-02 NLS-INV-202512-0148 株式会社ブルースカイテクノロジーズ 160-8810 東京都新宿区西新宿4-18-9 ブルースカイビル7F 青空 技術 03-5789-2241 640000 64000 7040000

▼請求書詳細テーブル

INVOICE_NUMBER QUANTITY DESCRIPTION UNIT_PRICE AMOUNT
NLS-INV-202512-0148 1 クラウド保守運用サポート 120000 120000
NLS-INV-202512-0148 2 サーバー監視設定作業 45000 90000
NLS-INV-202512-0148 3 データ移行作業 30000 90000
NLS-INV-202512-0148 1 API連携費 85000 85000
NLS-INV-202512-0148 5 ドキュメント作成 8000 40000
NLS-INV-202512-0148 2 技術コンサルティング(2h) 12000 24000
NLS-INV-202512-0148 1 テスト環境サポート 55000 55000
NLS-INV-202512-0148 1 セキュリティ診断 98000 98000
NLS-INV-202512-0148 1 メールサポート(月額) 10000 10000
NLS-INV-202512-0148 1 バックアップ設定 28000 28000

まとめ

非構造化データから、データを起こす際、結構大変で気が滅入ってしまいますよね。
特に画像データは、PDFと違い記載文言をコピペできないので、手入力となり、より大変ですよね。
AIの力を借りることによって、効率化をできたのではないしょうか。
データを起こす項目数が多くなっても、ファイル数が多くなっても、これなら怖くない?!

今回2つのSnowflakeのAI機能を使った結果、以下使い分けをしていくのが、良いのかなと感じました。

参考:AI_COMPLETE と AI_EXTRACT の違い

ざっくりいうと…

機能 特徴 向いてるケース
AI_EXTRACT 項目抽出に特化。指示がシンプル まずはこれを使うべき
AI_COMPLETE プロンプトの指示で柔軟に対応できる 項目横断のルールや複雑な指示が必要なとき

尚、私の業務シーンでは、
・微妙な字下げが意味を持っていたり
・複数の日付を全部西暦変換してほしい際に、項目ごとにプロンプトを記載するのが面倒
・プロンプトのチューニングが中々思うようにいかなかった
などあり、AI_COMPLETE を使用することにしました。

AI_EXTRACT関数でのプロンプトのチューニングを上手くやる方法は、またチャレンジしていければと思います。

Discussion