見出し画像

Snowflake Cortex Analystを試してみた

※ この記事はnote株式会社 Advent Calendar 2024の5日目の記事です。

noteでデータエンジニアのリーダーをやっています。久保田です。

LLMが色々な業務を効率化しているこの昨今、データ活用周りでもたくさんのサービスが生まれています。

その中でもやはり注目は、「SQLを書かずに、自然言語でデータの分析」という分野ではないでしょうか。

データ活用の重要性が叫ばれ、各企業が自身のサービスのデータを収集し活用していっていると思います。
しかし、データ活用は簡単なものではないです。データを活用するためにはそのデータへの知識が必要となります。

例えばnoteであれば
とあるクリエイターの記事のPVを集計して、タイトル別に出したい
とします。

これを素のテーブルを使って集計しようとすると、以下の操作が必要になります

  1. 以下のテーブルを結合

    1. 閲覧履歴が入っているテーブル

    2. note記事テーブル

    3. クリエイターの情報が入っているテーブル

  2. note記事データのタイトルカラムをgroup by

  3. select文を書き、countする

  4. 閲覧履歴のテーブルはそのままだと重いので、ログの発生時刻のカラムをwhere句で絞りこむ

知っていれば簡単ですが、知らないとまずどこのテーブルを使えばいいのか?どのテーブルを結合すればいいのか?というところからスタートします。

やりたいことは非常に単純なのに、解決方法が複雑に感じます。

そのためにデータカタログを整えるわけですが、データカタログにある数百のテーブルから目的のテーブルを探すのも時間がかかります。
テーブルによってはカラムがとても多いかもしれませんし、そこから探すだけでもかなり労力がかかります。

目的のテーブル・カラムを見つけたいだけならそれで何とかなるかもしれませんが、集計となると、今後はSQLの知識が必要なります。

上記の例ならば単純なcount(1)ですが、そうでなかった場合、SQLの知識の有無で結果が変わってきてしまう可能性があります。
例えば、ユニークユーザー数でcountをしたいとした時、count(distinct user_id)としなければなりません。

そういった知識による差を埋めるため、データマートを整えてあらかじめ集計して提供するわけですが、そうすると今後はデータマートにあるデータしか見れません。新しいデータを見たいとなると、データエンジニアに依頼して、というフローになります。スピード感が落ちてしまうので、あまり嬉しくはないですね。

なので結局、データに詳しいアナリストに相談して工数がかかってしまったり、最悪の場合は諦めてしまったりする、ということになってしまいます。

そこで今回は、Snowflakeから提供されているCortex Analystを検証してみたいと思います。
Cortex Analystは
Snowflake内のテーブルデータに対して自然言語で問い合わせを行う仕組みを簡単に構築
できるものです。

早速試してみます。

目的としては、「とあるクリエイターの記事のPVを集計して、タイトル別に出したい」という要望に柔軟に叶えられる仕組みを構築します。
cortex analystのざっくりとした仕組みは以下のようになっています。


すごく簡素に書いています



なので、まずはセマンティックモデルを作成し、アップロードする必要があります。
テーブルは今回のテスト用に以下のようなものを作成しました。

create database cortex_analyst_sample;

create or replace table article_pv_logs (
    id integer,
    article_id integer,
    user_id integer,
    created_at datetime
);

insert into article_pv_logs values
(1,1,1,'2024-12-01 00:00:00'),
(2,1,2,'2024-12-01 00:10:00'),
(3,1,3,'2024-12-01 00:12:00'),
(4,1,4,'2024-12-02 01:00:00'),
(5,1,5,'2024-12-02 04:00:00'),
(6,2,1,'2024-12-04 00:00:00'),
(7,2,2,'2024-12-02 00:00:00'),
(8,2,3,'2024-12-03 00:00:00'),
(9,2,6,'2024-12-02 07:00:00');
(10,3,6,'2024-12-02 07:00:00');


create or replace table articles (
    id integer,
    user_id integer,
    title string,
    created_at datetime
);

insert into articles values
(1, 1, 'title_A', '2024-12-01 00:00:00'),
(2, 2, 'title_B', '2024-12-02 00:00:00');
(3, 1, 'title_A2', '2024-12-02 00:00:00');

create table users (
    id integer,
    name string,
    created_at datetime
);

insert into users values
(1, 'user_A', '2024-12-01 00:00:00'),
(2, 'user_B', '2024-12-01 00:00:00'),
(3, 'user_C', '2024-12-01 00:00:00'),
(4, 'user_D', '2024-12-02 00:00:00'),
(5, 'user_E', '2024-12-02 00:00:00'),
(6, 'user_F', '2024-12-02 00:00:00');

セマンティックモデルは以下のようにしてみました。

name: sample
tables:
  - name: ARTICLES
    description: 記事データが保存されているテーブル
    base_table:
      database: CORTEX_ANALYST_SAMPLE
      schema: PUBLIC
      table: ARTICLES
    primary_key:
      columns:
        - id
    dimensions:
      - name: TITLE
        synonyms:
          - 記事タイトル
          - 記事名
          - title
          - タイトル
        description: 記事のタイトル
        expr: TITLE
        data_type: TEXT
        sample_values:
          - title_A
          - title_B
      - name: ID
        synonyms:
          - ''
        description: 記事ごとにユニークに割り振られるユニークID
        expr: ID
        data_type: NUMBER
        sample_values:
          - '1'
          - '2'
      - name: USER_ID
        synonyms:
          - 記事を作ったユーザーID
          - ユーザーID
        description: 記事を作ったユーザーのID
        expr: USER_ID
        data_type: NUMBER
        sample_values:
          - '1'
          - '2'
    time_dimensions:
      - name: CREATED_AT
        synonyms:
          - 記事の作成時刻
          - 記事の作成日時
        description: 記事が作成された時間
        expr: CREATED_AT
        data_type: TIMESTAMP_NTZ
        sample_values:
          - '2024-12-01 00:00:00'
          - '2024-12-02 00:00:00'
  - name: ARTICLE_PV_LOGS
    description: ユーザーの記事の閲覧履歴が入っているテーブル
    base_table:
      database: CORTEX_ANALYST_SAMPLE
      schema: PUBLIC
      table: ARTICLE_PV_LOGS
    primary_key:
      columns:
        - id
    dimensions:
      - name: ID
        synonyms:
          - ログID
        description: ログの発生のたびに割り振られるユニークID
        expr: ARTICLE_ID
        data_type: NUMBER
        sample_values:
          - '1'
          - '2'
      - name: ARTICLE_ID
        synonyms:
          - 記事ID
        description: ユーザーが閲覧した記事のIDが入っている
        expr: ARTICLE_ID
        data_type: NUMBER
        sample_values:
          - '1'
          - '2'
      - name: USER_ID
        synonyms:
          - ユーザーID
        description: 記事を閲覧したユーザーのIDが入っている
        expr: USER_ID
        data_type: NUMBER
        sample_values:
          - '1'
          - '2'
          - '3'
    time_dimensions:
      - name: CREATED_AT
        synonyms:
          - 閲覧時刻
          - 閲覧日時
        description: ユーザーが記事を閲覧した日時
        expr: CREATED_AT
        data_type: TIMESTAMP_NTZ
        sample_values:
          - '2024-12-01 00:00:00'
          - '2024-12-01 00:10:00'
          - '2024-12-01 00:12:00'
  - name: USERS
    description: ユーザーの情報が入っているテーブル
    base_table:
      database: CORTEX_ANALYST_SAMPLE
      schema: PUBLIC
      table: USERS
    primary_key:
      columns:
        - id
    dimensions:
      - name: NAME
        synonyms:
          - ユーザー名
        description: ユーザーが自身で設定したユーザー名
        expr: NAME
        data_type: TEXT
        sample_values:
          - user_A
          - user_B
          - user_C
      - name: ID
        synonyms:
          - ユーザーID
        description: ユーザーごとに割り振られるユニークなID
        expr: ID
        data_type: NUMBER
        sample_values:
          - '1'
          - '2'
          - '3'
    time_dimensions:
      - name: CREATED_AT
        synonyms:
          - ユーザーの登録日時
        description: ユーザーが登録した日時が入っている
        expr: CREATED_AT
        data_type: TIMESTAMP_NTZ
        sample_values:
          - '2024-12-01 00:00:00'
          - '2024-12-02 00:00:00'
relationships:
  - name: ARTICLE_PV_LOGS_to_ARTICLES
    left_table: ARTICLE_PV_LOGS
    right_table: ARTICLES
    join_type: inner
    relationship_type: many_to_one
    relationship_columns:
      - left_column: article_id
        right_column: id
  - name: ARTICLE_PV_LOGS_to_USERS
    left_table: ARTICLE_PV_LOGS
    right_table: USERS
    join_type: left_outer
    relationship_type: many_to_one
    relationship_columns:
      - left_column: user_id
        right_column: id
  - name: ARTICLES_to_USERS
    left_table: ARTICLES
    right_table: USERS
    join_type: left_outer
    relationship_type: many_to_one
    relationship_columns:
      - left_column: user_id
        right_column: id

ポイントはrelationshipsの部分で、最近joinができるようになりました。

では実行してみます。
https://github.com/Snowflake-Labs/semantic-model-generator
こちらで公開されているデモアプリ経由で試してみます。




質問を入力して実行すると、SQLが実行され、結果が表示されました。


少し条件を加えて、2024年12月2日以降のPVのみを条件に指定してみます。


いい感じですね。
最後に、セマンティックモデルに記載していない、つまり知らないことを聞いてみます。


ちゃんとわからないと答えてくれましたね。

非常に簡単な内容ではありましたが、cortex analystでデータ活用の課題を解決する可能性が見えたかな、と思います。

所感としては、やはりセマンティックモデルをどれくらい整えられるか、が非常に重要かなと感じました。(一度relationshipsのところを間違えていて、集計結果がずれてしまっていた)
なので、全てのモデルに対して、ではなく、しっかりとデータを整えた上で必要なモデルの必要なカラムを提供する、というのがいいのではないか、と感じています。

今までのようにデータ基盤を作ってはいどうぞ、ではなく、データ活用をしやすいようにセマンティックレイヤーを整える、ということもデータエンジニアの役割になってくるのではないでしょうか。

取り急ぎnoteでは早く社内で使えるようにしていきたいと思います。
ありがとうございました。

▼noteエンジニアアドベントカレンダーはこちら

https://qiita.com/advent-calendar/2024/note

▼さらにnoteの技術記事が読みたい方はこちら

https://engineerteam.note.jp/

いいなと思ったら応援しよう!