Timee Product Team Blog

タイミー開発者ブログ

LeSS Yoake ASIA 2024 Day1 レポート

こんにちは! スクラムマスターを担当している吉野です!

株式会社タイミーはLeSS Yoake ASIA 2024のスポンサーとして参加し、私も招待チケットを利用して現地に行ってきました!

本記事ではDay1のコンテンツのいくつかをレポートします!

Opening Session

オープニングキーノートは、Craig Larmanさんによる "AI & HR: Evolving Organizations in an AI World" というタイトルで、AIが私たちにもたらしてくれる変化を、AIができることの紹介、AIの変化に合わせて個人の役割の変わり方からチームのあり方の変化、と、徐々にスコープを広げて話されていました。

特に印象的だったのは、一部の専門性をAIが担ってくれる未来はそう遠くないというお話でした。

現在は各スペシャリストで構成されています。 それは、各メンバーがバリューを個々の専門性の領域で発揮しているからとなります。

チームメンバーの専門性が特別必要な領域や、ルーティンワークを必要とする業務は、AIにお任せすることで、個人の時間に余裕を持たせることができます。余裕ができた時間で何をするのか? それは、学習です。それも自身の専門性を深める学習ではなく、他の領域についても学ぶことが大切とのことでした。

そうすることで、個々が専門性を高めるチームではなく、様々なことに関わることのできるメンバーでチーム内の協働を促進し、よりチームの透明性を高められるということでした。

クロスファンクショナルなチームを作ることに苦労されているお話をよくお聞きしますが、このようにAIを使うことで、チーム組成を進めることができるとのこと。

(GLAD Developer = Generative-AI & LLM-Assisted Development)

そして、将来は一人の開発者と複数のAI Agentsの可能性も…

AIが専門性を担ってくれる可能性と、チームの形の可能性を一つ知れたセッションでした。

スポンサーセッション(Red Hat)

Red Hatさんによるスポンサーセッションでは、いくつかのチームでの議論を通しつつ、チームのスクラム/LeSSをより促進させるためには、組織変革へ目を向ける必要があることをメインに話されていました。

また、その組織変革に必要な要素を表す「スターモデル」を通して戦略/構造/プロセス/リワード/人材の考え方について、具体的な例を通しての説明がありました。

実際に使用し、方針を現場で立てるには、各項目のつながりとWhyとなる軸は説明できる必要があると思いますが、観点が簡潔にまとまっているモデルで、とっかかりに使えそうな印象を受けました。

また、その組織を変えることができる人物は「スクラムマスター」とのことです。

現在のタイミーでは「Agile Practice Team」というスクラムマスターで構成される、組織に向き合うチームがあります。

私も所属しているチームで、この発表はチームの存在意義を言語化してくれている!という気持ちになりました。

その他にも、ディスカッションの時間もあり、チームで多くの意見を出し合いました。

1時間とは思えない密度のセッションでした!

The LeSS Company CEOによるトークセッション

フルスタックCEOというパワフルな自己紹介をされていた、The LeSS Company CEOのBastiaan氏によるセッションでした。

LeSSの広がりやどのような場で活用されているのか、世界レベルでのお話を聞くことができました。

また、本セッションテーマについて、次のセッション時間に直接お話を伺いしました。

Bastiaanさん、Basさん、Akiさんとの廊下トーク

本来であれば、LeSS Morning 主催のワークショップの時間だったのですが、偶然にも廊下で3人のお姿を見つけて、話しかけてみました。

お話しした内容のうち、いくつかを以下に記載します。

最適なスケールフレームワークを選択するには? A. やりたいことをマネージャーなどに伝えるのではなく、まずは経営層の困っていることなどに寄り添うこと。システムモデリング(思考)などを使用し、困っていることを明確にする。 その中で、いくつかのフレームワークを当てこんだ時にうまくいくのか、うまくいかないのか、どのようなデメリットがあるのかを明確にする。 まずは、経営層の困っていることやプロダクトの課題を見える化することが大切。 特に、昨今はチームの認知負荷を減らすことが重要視されている傾向がある。多くの経営層の悩みにつながっており、あなたの場でも関係する可能性があるので見てみると良い。

Stage of Agileのデータから、LeSSの割合が少なくなっていて、SaFEの割合が多くなっている。これはなぜなのか? A. ガードナーに伺ったところ、実際のLeSS利用率は増えている。ガードナーは7000人にヒアリングしている。State of Agileの方は1000人しかデータを取っていないので、どのような人に向けてのアンケートかで、内容が変わってしまう。また、その人の意思とは反するデータになっているケースもある。例えば、ボスが変わってしまったことで、利用しているフレームワークがガラッと変わってしまうなど。なので、データの信憑性としてはそこまで高いものではないため、ある程度参考値ぐらいに考えた方が良い。

(名刺もいただきまして、「困ったらいつでも連絡して欲しい!」とオープンに接してくれたのがめちゃくちゃ嬉しかったです!)

スポンサーセッション : LINEとヤフーそれぞれの組織でのLeSS実践奮闘記

LINEヤフーより、nakoさん(@nako418)の登壇でした。

LeSSに挑戦し、難しい点に当たりつつもLeSSの実践を進めていったお話でした。

印象的だったのは、常に何ができるのかという選択肢を考え、一番最適な形を選択し続ける動きをされていたことです。

例えば…

  • フィーチャーチームとコンポーネントチームのどちらが良いのか?(理想と現時点)
  • オーバーオールイベントの参加者はどのような人を集めるのか?

など、要所要所の考える必要があるポイントでしっかりと選択肢を洗い出し、都度最適と思えるものを理由と合わせて選択して実践していくことは、とても参考になりました。

また、困ったお話についても、バックログの整理方法など多くの人が向き合うことになりそうな問題をピックアップされていて、すごく共感が多かったセッションでした!

(整理は、ひとまずエピックレベルで並び替え、必要になる上位のものに一旦フォーカスしていくとのことでした)

Q&A Craigさん / Basさんに質問Time

一度業務で抜けたため終盤のみの参加でしたが、それでも濃い質問と鋭い返答が多い印象でした。

例えば…

質問 : マネージャーがいない組織における、責任の所在は?生産性の可視化ができていない、となった場合の問題は誰が責任を負うのか?マネージャーがいない組織において、どのように解決していくのか。

回答 :

  • チームが責任を持つことが大切
  • スクラムマスターがそれを促す
  • 人数の少ないマネージャーができるのであれば、人数の多いチームメンバーもできるのではないか?

“マネージャーでないとできない” という制約を個人の中に持ってしまっていたことに気がついた瞬間でした。大切なのは、“なぜチームが気にしないのか” ということを考え、システムとシステム構造を変えることが大切と話されていました。

ディナー

(写真を撮っていなくて残念…) 8種類ぐらいのビールと美味しそうな夕食が並んでいて、ビュッフェスタイルの懇親会でした。 ビールを何回もおかわりしつつ、多くの方とお話しして回りました。

そのため、夕食にはほとんど手をつけず…

イベント全体で時間が押していたため、1時間と短めの懇親会でした。 (もっと多くの方と交流したかった…!!)

終わりに

以上でDay1のレポートとなります! 運営の方にお話を伺ったところ、初めての大規模開催とのことでした。

機材トラブルや時間が押してしまった等、いくつか大変そうなシーンもありましたがあの規模のカンファレンスを開催されていたのはめちゃくちゃすごかったです! (同じ規模のイベントをいつか私も開催したい)

まだDay5がありますので、引き続き楽しみつつ学んでいきたいと思います!

データアナリストの講義を大学で行ってきました!

こんにちは! データアナリストの@takahideです。
タイミーではプロダクト向き合いの分析業務を行なっています。

先日、東京都立大学の経済経営学部にてデータアナリストの講義を行わせて頂きました。
データアナリストの魅力やアカデミックな知の重要性に改めて向き合うことができたので、ご紹介できたらと思います。



内容は以下になります。

講義の背景

講義に至った背景は、知り合いでもある米田泰隆准教授とお話しした際に、データアナリストの業務内容が学生の皆さんの興味と合致するのでは、と意気投合したことでした。

今回お伺いしたのはゼミ形式の講義で、計量経済学から最新のデータサイエンスまで幅広い知見に基づいたデータ分析の授業が行われていて、業務内容との整合性も高いと感じました。

講義内容

講義は大きく下記テーマを扱いました。本ブログでは、1、3、4を中心にお話します。
1.タイミーの事業と組織に関して
2.データアナリストになるまで
3.データアナリストの業務
4.アカデミックな知との繋がり

事業と組織に関して

まずは、タイミーの事業説明を行いました。
タイミーはワーカーと企業の双方が出会うツー・サイド・プラットフォームであり、分析対象となるデータも「ワーカー」「企業」「マッチング」に関するものが中心となります。
ビジネスモデルは一見単純に見えますが、ワーカーと企業の複雑な意思決定を読み解く必要があり、データアナリストとして非常にやりがいがあります。

次に、タイミーのデータアナリストの組織に関してお話ししました。
大きくは「プロダクトアナリティクス」と「ビジネス&マーケティングアナリティクス」という2つのグループに分かれていて、各グループが、担当領域に対して分析で得られたインサイトを提供しています。

例えば、プロダクトアナリティクスグループであれば、顧客に提供する価値体験ごとにチームが組成され、各チームにデータアナリストがアサイン、チームの責任者と協働して分析業務に携わります。

また、チーム単位の分析とは別に、会社横断での分析も行っていて、こちらはプロダクト✖︎マーケティングのようにグループ横断のものも多いです。

データアナリストの業務内容

こちらのパートでは、データアナリストの業務内容を説明しました。
タイミーのデータアナリストは、プロダクト、マーケティング、ビジネスのメンバーと伴走しながら、意思決定をサポートしています。
データアナリストは、データを用いた分析をもとに、全社戦略や事業に貢献することが期待されています。自分が行った分析がきっかけで、顧客に価値を届けられた瞬間は非常に大きな達成感を得られます。

では、「データを用いた分析」を進める上で必要になるものとは何になるのか?
「データを用いた分析」なので複雑な分析スキルが重要と思われがちですが、個人的には「仮説構築」が最も大切だと感じています(もちろん高度な分析スキルが不要というわけでは全くないです)。

「分析」を上流工程から下流工程へのプロセスと考えると、上流工程で作られた仮説に基づいて様々な定量・定性分析が行われます。そのため、仮説が間違っていると、定量・定性分析自体も間違った結論を出すことになってしまいます。

仮説の精度を上げる手法は色々ありますが、重要なのが「言語化」だと考えています。
仮説構築を「何気ない問いを、定義を確認し、抽象化して解像度を上げる一連の流れ」と考えると、「個人的な問い」をメンバー間で納得できる「共通言語」に仕立てていくことが大切になります。

アカデミックな知の活用

最後は、データアナリストとアカデミックな知の繋がりに関してお話ししました。
アカデミックな知は先ほどの「言語化」を考える上で非常に重要だと考えています。

個人的に、データアナリストの業務を長く続けるにつれて、アカデミックな知の価値を強く感じることが多くなってきました。
向き合う課題が複雑であるほど、それを解くためのアイディアも多様な切り口が求められますが、アカデミックな知はそうした切り口の宝庫になっていると感じます。

具体例をいくつか挙げてみたいと思います。

経済学
- 経済学の一分野であるマーケットデザインはマッチングの最適化を考える上で参考になります。
統計学
- プロダクト開発では、施策の効果判断を行う際にランダム化比較試験を行います。この背景には統計学の知見があります。
人類学
- ユーザーの声を知ることはプロダクト開発において非常に重要ですが、定性調査の各種手法の背景には人類学や社会学の知見があります。
論理学
- 仮説を構築する上で、演繹的推論、帰納的推論といった古典的な推論が必要になります。また、仮説的推論は創造的な思考を生み出すヒントになります。

これらの知見は、必要な時に使える便利なツールではないですが、様々な観点でものごとを捉えられるほど「言語化」が捗り、結果として仮説構築など分析の重要なプロセスを推進しやすくなります。

講義の御礼

改めて、今回データアナリストの講義を行わせて頂きありがとうございました!

データに対する理解度が高い方が多く、また、ご自身で起業されていて分析の勘所を備えているなど、お話しして非常に大きな刺激を受けました。
大学で学べることを羨ましく思いつつ、アカデミックな知と業務との繋がりをこれからも作っていきたいと思いました。

最後に

今回は、データアナリストの外部活動として、大学での講義に関してお話ししましたが、きっかけは「大学で講義を行いたい」という提案でした。

タイミーでは、メンバーの意見を真摯に聞いて、サポートしてくれる文化があります。
年次に関わらず分析プロジェクトの提案ができ、新しいことにチャレンジしたい方にとって非常に魅力的な環境だと思います。

We’re Hiring!

私たちは、ともに働くメンバーを募集しています!!
カジュアル面談も行っていますので、少しでも興味がありましたら気軽にご連絡ください。 hrmos.co

CircleCIからGitHub Actionsへ移行、テスト実行時間をp95で15分から6分に短縮!移行時の課題と解決策

エンジニアリング本部 プラットフォームエンジニアリングチームの徳富です。我々のチームでは、CIパイプラインの効率化と開発体験の向上を目指し、CircleCIからGitHub Actionsへの移行を進めてきました。移行によってテスト・静的解析(以降CIと記載する)の実行時間をp95で9分短縮しましたが、この移行にはいくつかの課題もありました。今回は移行の背景や移行時の苦労について紹介します。

本記事のまとめ

  • CircleCIからGitHub Actionsに移行し、CI実行時間をp95で9分短縮
  • 並列実行やテスト結果の連携における課題を解決し、効率化を実現
  • テスト結果のPR通知や分割テストの仕組みを工夫し、開発体験を向上

CircleCIからGitHub Actionsへ移行した背景

以前利用していたCircleCIのPerformanceプランでは、並列実行できるジョブ数が80に制限されていました。1回のCI実行に40の並列ジョブを使用していたため、同時にCIを実行できる開発者は最大2名まで。この状況では、今後開発者が増加するにつれて、CIの待ち時間が長くなるリスクを抱えていました。プランのアップグレードも検討しましたが、以下の理由からGitHub Actionsへの移行を決断しました。

理由1: 学習コストの削減と効率化

弊社では基本的にGitHub Actionsを利用していますが、RSpecテストと静的解析のみにCircleCIを使用していました。これをGitHub Actionsに統合することで、CircleCIとGitHub Actionsの両方を学ぶ必要がなくなり、開発者の学習コストが削減されます。また、以前はCircleCIでのCI完了後に、デプロイをGitHub Actionsで行うワークフローでした。CIの実行基盤をGitHub Actionsに移行することで、テストもデプロイもGitHub Actionsに統一できるようになります。これにより、デプロイフローがよりシンプルになり、メンテナンス性も向上しています。

理由2: セキュリティリスクと管理の効率化

CIプロバイダーをGitHub Actionsに一本化することで、複数のプロバイダーを管理する必要がなくなり、情報流出のリスクが低減し、一貫したセキュリティ対策を実施できます。さらに、管理するツールが減ることで管理業務が簡素化され、運用が効率的になります。

移行する上での課題となっていたポイント

  1. テスト実行時間ベースでテスト分割する仕組みがGitHub Actionsにない
  2. テストの失敗した情報をわかりやすく参照できるUIがない
  3. matrix strategyを使って並列実行をすると後続のjobに結果を送れない
  4. Flakyテストを一覧で参照できない

1. テスト実行時間ベースでテスト分割する仕組みがGitHub Actionsにない

CircleCIには、CircleCI CLI を使用してテストファイルを実行時間ベースで分割する機能がありましたが、GitHub Actionsには同様の機能がありませんでした。

そこで、代替としてmtsmfm/split-testライブラリを導入し、RSpecテストを均等に分割する仕組みを整えました。このライブラリは、過去のテスト実行時間をもとに、実行時間が均一になるようにテストファイルを分割します。そのためデフォルトブランチのテスト結果をS3に保存し、その結果を利用してテストを効率的に分割・実行するフローを構築しました。

2. テストの失敗した情報をわかりやすく参照できるUIがない

CircleCIには、テスト結果をわかりやすく表示する機能が標準で備わっており、開発者はテストの成否や詳細を簡単に確認できました。しかし、GitHub Actionsにはそのような標準機能がなく、開発者がテスト結果を確認するのに手間がかかってしまうという課題がありました。

そこで、SonicGarden / rspec-report-actionにパッチを適用し、テスト結果をPRにコメントする仕組みを導入しました。この改善により、CircleCIにログインせずにPR内で直接テスト結果を確認できるようになり、作業効率が向上しました。

3. matrix strategyを使って並列実行をすると後続のjobに結果を送れない

GitHub Actionsでは、matrix strategyを使うことで、並列実行ができます。しかし、この並列実行には問題があり、後続のジョブにテスト結果を渡せないという課題がありました。

最初は、各マトリックスで生成されたテスト結果をアーティファクトとしてアップロードし、後続のジョブでダウンロード・集計する方針を検討しました。しかし、25並列で実行していたため、アーティファクトのアップロード頻度が増加し、すぐにGitHub Actionsのレート制限に達してしまいました。

この問題に対処するため、テスト結果をGitHub Actionsのアーティファクトではなく、S3にアップロードする方法に切り替えました。これにより、レート制限の問題を回避でき、後続のジョブでテストの結果をPRに投稿する仕組みが無事に機能するようになりました。

4. Flakyテストを一覧で参照できない

CircleCIではテストインサイトを使ってFlakyテストを確認できましたが、GitHub Actionsにはそのような機能がありませんでした。当初はCodecovのTest Analyticsを使ってFlakyテストを確認していましたが、絞り込み機能が不十分で、ページの表示に時間がかかるという問題がありました。

そこで、現在はDatadog Test Visibilityを利用してFlakyテストを確認しています。Datadogを使用することで、テストのTrace情報などの詳細なデータを収集できるだけでなく、不安定なテストが検出された際にアラートを設定することも可能になりました。

完成したワークフローの一例

ここで、最終的に完成したワークフローの一部をご紹介します。GitHub Actionsへの移行を検討している方にとって、少しでも参考になれば幸いです。

name: ci

on:
  push:
    branches:
      - '**'
    tags-ignore:
      - '*'

concurrency:
  group: ${{ github.workflow }}-${{ github.ref }}
  cancel-in-progress: true

permissions:
  id-token: write
  contents: read
  pull-requests: write

jobs:
  generate-matrix:
    runs-on: ubuntu-latest
    timeout-minutes: 1
    outputs:
      parallelism: ${{ steps.set-matrix.outputs.parallelism }}
      ids: ${{ steps.set-matrix.outputs.ids }}
    steps:
      - id: set-matrix
        run: |
          parallelism=25 # テストの並列数
          ids=$(seq 0 $((parallelism - 1)) | jq -s | jq -c)
          echo "parallelism=[$parallelism]"
          echo "ids=$ids"
          echo "parallelism=[$parallelism]" >> "$GITHUB_OUTPUT"
          echo "ids=$ids" >> "$GITHUB_OUTPUT"

  rspec:
    needs: [generate-matrix]
    runs-on: ubuntu-latest
    timeout-minutes: 20
    env:
      DD_CIVISIBILITY_AGENTLESS_ENABLED: true # Datadog Test Visibility用
      DD_API_KEY: ${{ secrets.DATADOG_API_KEY }} # Datadog Test Visibility用
      DD_ENV: ci # Datadog Test Visibility用
    strategy:
      fail-fast: false
      matrix:
        parallelism: ${{ fromJson(needs.generate-matrix.outputs.parallelism) }}
        id: ${{ fromJson(needs.generate-matrix.outputs.ids) }}

    services:
      # rspec実行に必要なコンテナを起動
   
    steps:
      - name: Generate token
        id: generate_token
        uses: actions/create-github-app-token@v1
        with:
          app-id: app idを指定
          private-key: キーを指定

      - name: Checkout
        uses: actions/checkout@v4
        with:
          token: ${{ steps.generate_token.outputs.token }}

      - name: Setup Ruby with caching
        uses: ruby/setup-ruby@v1
        with:
          ruby-version: 3.3
          bundler-cache: true

      - name: Configure AWS credentials
        uses: aws-actions/configure-aws-credentials@v4
        with:
          role-to-assume: # S3にアクセスできる権限をもつロールを指定
          aws-region: # リージョン名

      # NOTE: デフォルトブランチで記録された各RSpecテストの実行時間データをダウンロード
      - name: Download rspec junit
        run: aws s3 cp s3://デフォルトブランチでのテスト結果(JUnit XML)が保存されているS3を指定 tmp/rspec_junit --recursive

      # NOTE: テストファイルを分割するためのツールをダウンロードし、後続ステップでテストファイルをダウンロードして分割する。
      #       これにより、マトリックスを使用して並列で実行されるRSpecテストが均等に分割され、
      #       すべてのテストジョブがほぼ同時に完了するようにする。
      - name: Split test file
        run: |
          curl -L --output split-test https://github.com/mtsmfm/split-test/releases/download/v1.0.0/split-test-x86_64-unknown-linux-gnu
          chmod +x split-test

      - name: RSpec
        run: |
          # テストファイルを分割しテストを実行する
          bundle exec rails db:create db:schema:load
          ./split-test --junit-xml-report-dir tmp/rspec_junit \
            --node-index ${{ matrix.id }} \
            --node-total ${{ matrix.parallelism }} \
            --tests-glob "spec/**/*_spec.rb" \
            --tests-glob "packs/*/spec/**/*_spec.rb" | xargs bundle exec rspec \
            --format progress \
            --format RspecJunitFormatter \
            --out report/rspec_junit/${{ matrix.id }}.xml \
            -f j -o report/results/${{ matrix.id }}.json \
            -f p

      # テストが完了したら、テスト結果をS3にアップロードし、後続のジョブで利用できるようにする
      - name: Upload test report
        if: always()
        run: |
          aws s3 cp report s3://テスト結果が保存されているS3を指定 --recursive

  rspec-status:
    runs-on: ubuntu-latest
    timeout-minutes: 1
    needs: [generate-matrix, rspec]
    if: ${{ !cancelled() && github.event_name == 'push' }}
    steps:
      - name: Check previous job status
        run: |
          if [ "${{ needs.rspec.result }}" == "success" ]; then
            echo "テスト成功"
          else
            echo "テスト失敗"
            exit 1
          fi

  upload-rspec-junit:
    runs-on: ubuntu-latest
    timeout-minutes: 2
    needs: [generate-matrix, rspec]
    if: github.ref == 'refs/heads/main' # デフォルトブランチを指定
    steps:
      - name: Configure AWS credentials
        uses: aws-actions/configure-aws-credentials@v4
        with:
          role-to-assume: # S3にアクセスできる権限をもつロールを指定
          aws-region: # リージョン名

      - name: Download rspec junit
        run: aws s3 cp s3://各マトリックスでのテスト結果が保存されているS3を指定 rspec_junit --recursive

      - name: Upload rspec junit
        run: aws s3 cp rspec_junit s3://各テストのJUnit XMLをアップロードするS3を指定 --recursive

  pr-comment:
    needs: [generate-matrix, rspec]
    if: ${{ !cancelled() }}
    runs-on: ubuntu-latest
    timeout-minutes: 2
    steps:
      - name: Generate token
        id: generate_token
        uses: actions/create-github-app-token@v1
        with:
          app-id: app idを指定
          private-key: キーを指定

      - name: Checkout
        uses: actions/checkout@v4
        with:
          token: ${{ steps.generate_token.outputs.token }}

      - name: Configure AWS credentials
        uses: aws-actions/configure-aws-credentials@v4
        with:
          role-to-assume: # S3にアクセスできる権限をもつロールを指定
          aws-region: # リージョン名
     
      - name: Download RSpec reports
        run: aws s3 cp s3://各マトリックスでのテスト結果が保存されているS3を指定 report --recursive

      - name: RSpec Report
        if: steps.find_pr.outcome == 'success'
        uses: SonicGarden/rspec-report-actionアクションに一部パッチを適用したアクションを指定
        with:
          token: ${{ steps.generate_token.outputs.token }}
          json-path: report/results/*.json
          comment: "${{ github.event_name == 'push' }}" # PRにコメントするかどうか
          pull-request-id: ${{ fromJson(steps.find_pr.outputs.pr_json).number }}
          hideFooterLink: true

得られた成果

テスト時間の短縮による開発効率の向上

GitHub Actionsへの移行により、p95でテスト実行時間が9分短縮されました。並列実行の制限がなくなったことで、CI/CDのパフォーマンスが大幅に向上しました。この改善により、開発者の作業効率が向上し、より早くフィードバックを得られる環境が整いました。

  • CircleCIの時はp95で15分

  • GitHub Actionsに移行後はp95でテストが6分程度で終わるようになっているになっている

移行のまとめと今後の課題

CircleCIからGitHub Actionsへの移行により、テスト実行時間の大幅な短縮という大きな成果を得られました。しかし、移行に伴う課題も少なくなく、とくにテスト結果の連携テストの分割には工夫が必要でした。

今後は、GitHub Actionsの新機能やさらなる最適化手法を活用し、テストやデプロイのより一層の効率化を目指していきます。本記事が、同様の課題に直面している方々の参考になれば幸いです。

dbt coalesce 2024 1日目のセッションを徹底解説(okodoon視聴分)

こんにちは。okodoooonです🌵

ラスベガスに来てから、同行しているメンバーと手分けをしてセッションを聞いて、知見をまとめる作業に追われており、なかなかハードな日々を過ごしておりました。

今回は初日に聞いた5つのセッションがどれも知見に溢れるものだったので、そちら紹介していきたいと思います💪

スライドが公開されたり他メンバー担当分の記事が上がり次第リンクなど追って貼っていきます。(2日目以降のやつも頑張って書いております)

目次

Data alone is not enough(訳:データだけでは不十分である)

発表者:Preston Wong (Analytics Engineer @ Settle)

概要

データを提供できる組織や環境を作るのではなく、洞察を提供できる組織や環境を作るべきで、
理想の組織に改善されるために、Settleが取り組んでいるJTBDというフレームワークの紹介をしていました

セッション内容の紹介

以下のような画像とこちらブログの引用ともに

  • レポーティング業務はデータ組織にとってゲートウェイドラッグのようなものだ
  • これらのレポートは本当に意味のあるものなのか?変化を促しているのか?実際に使用されているのか?誰かがそれを見て、2秒で終わるために7時間も費やすのはなぜだろう?
  • 最近のデータイニシアチブは、情報へのアクセスを民主化することに重点を置きすぎており、ビジネスへの影響を促進することに十分に注力されていない。どんなに多くの情報があっても、それだけでは組織の変革を促すことはできない。

という強烈なメッセージを発信していました。

とても耳が痛いですね。

ビジネスインパクトをいかに生み出すか」という観点なしに、ただデータを出力し続けるチームになってしまうことへの懸念を紹介してくれました。

それらの懸念を紹介した後に「データチームがどのようにしてビジネスのデータが持つ潜在能力を最大限に引き出せるのかを考える必要がある」と続き、

レポーティング業務から抜け出せない理由はコンテキストを持っていないことが多いからと説明していました。

良い例として、Q3の新規アクティブ顧客数が安定して増加しており、最近の月では20%増加したことが挙げられます。データ担当者がこれに気づいたとしても、直接的な文脈を持っているとは限りません。このデータには、最近の企業買収があったことや、その顧客基盤を取得したことが含まれておらず、それが20%増加の理由です。この説明はデータ自体では行えず、他の誰かが説明する必要があります。つまり、なぜそうなったのかを答えるのは難しいのです。

Settleではデータチームを適切にステップアップさせていくためにデータ組織のJTBD(JobToBeDone)を設定しており、その運用によってレポーティング組織から適切に脱却しつつあると紹介しています。

  • JTBD of Modern Data Team
    • データの活用
    • メトリクス管理
    • プロアクティブなインサイト
    • 実験のドライブ
    • データとのインターフェース

紹介されていた各要素ごとの課題例のproblemとimpactがこちらです(ちょっと文量が多いので畳んでいます)。

データの活用(クリックすると展開)

  • データの活用
    • オペレーショナルデータを必要とするチームに提供すること
    • ex.
      • マーケティング部門からのリクエストで「ハブスポットで解約した顧客に自動メールを送信し、タッチポイントとアウトリーチを行いたい」
      • 解決したHow
        • 多様なソースからのデータを、主に内部データを含めて、dbtモデルに統合。このデータマーケットは、ビジネスの包括的な表現として機能し、意思決定に不可欠な業務属性、将来のフラグ、メトリクスおよびSSoTを提供。
        • リバースETLと組み合わせることで、各チームの好みや主要なSaaSツール(SalesforceやHubSpot、Intercomなど)にシームレスに同期されたSSoTを持つことが可能となり、効率的なデータ活用とリアルタイムのインサイトが実現可能。
      • インパクト
        • このワークフローを合理化し、データを取得して作業を行うのに何時間も費やす代わりに、数分で済むようになった。
        • このアプローチにより、彼らはツールセットを簡素化し、結果として効率的なセルフサービスモデルを実現。
        • マーケティングチームは最新の関連データに直接アクセスでき、タイムリーかつ正確に実行できるようになった。

メトリクス管理(クリックすると展開)

  • メトリクス管理
    • 共有された定義と重要な事実の基準を作成すること
    • ex.
      • もしファイナンスのステークホルダーに尋ねれば「アクティブカスタマー」とは、自分の銀行口座を接続した人だと言うでしょう。マーケティングに聞けば「アクティブカスタマー」は、完全なオンボーディングフローを完了した顧客だと言います。しかし、プロダクトに尋ねると「アクティブカスタマー」は、最近プラットフォーム上で活動があった顧客だと言います。では、どれが本当に正しいのでしょうか?
      • 解決したHow
        • セマンティックレイヤーを活用することで、これらのメトリクスを明確に定義し、文書化。
      • インパクト
        • Hexのようなツールや、ExcelやGoogle Sheetsを好むステークホルダーがアドホックレポートを作成する際にも使用可能に。
        • 指標に関する煩わしい問い合わせ対応が大幅に減少。

プロアクティブなインサイト(クリックすると展開)

  • プロアクティブなインサイト

    • プロアクティブ(=先手を取れる)ようなデータの提供 (= 先行指標を提供)
    • ex.
      • 顧客の解約が若干増えているが、どのデータが私たちが顧客を維持するためによりプロアクティブになる手助けをしてくれるか?
      • 解決したHow
        • 戦略的リーダーを特定、ビジネスユニットと密接に連携
        • 「アシュアランススコア」を開発
        • 顧客がサービスを解約する可能性を定量化し、チームが迅速に行動を起こすためのアラートを受け取れるようにする
      • インパクト
        • 。このデータ駆動型のアプローチにより、リスクのある顧客を早期に検出し、ターゲットを絞った介入措置を講じることが可能に。
        • 顧客のライフタイムバリューを向上させ、会社の長期的な成功と持続可能な成長において重要な役割を果たすことに成功。

実験のドライブ(クリックすると展開)

  • 実験のドライブ

    • プロアクティブなインサイトの発見と連携しながら、ビジネスに対して測定可能な影響を与えるための実験を推進すること
    • ex.
      • 現在使用している機能に問題が発生しました。リスクを高めたり、ビジネスへの影響を評価したりするために利用できるデータポイントはあるか?
      • 解決したHow
        • 組織内のステークホルダーと協力して、実験を展開
      • インパクト
        • 全体のスコアを向上させることができ、非常に洞察に富んだ重要な結果を得ることに成功

データのインターフェース(クリックすると展開)

  • データのインターフェース
    • ビジネス全体にわたるチームメンバーに必要な情報や結論を提供し、彼らがそれを活用できるようにすること
    • ex.
      • この収益はどこから来ているのか?モデルでどのように定義されているのか?この数字を週次レポートに使用しても良いのか?
      • 解決したHow

        • 彼らが自分自身で質問を探求し、答えを見つけるために必要なツールを提供できるようにする
        • description生成をAIに実行してもらいその内容をチェックするプロセスを実行する
        • dbtとmetabaseを接合して、metabase上でdbt exploreと同様のメタデータを閲覧可能とする
      • インパクト
        • 最終的にデータチームのレポーティング作業負担を軽減

JTBDのマトリクスは最終的にこのような形になります。

Settle社による所見

  • 生のデータ出力だけでは不十分であり、JTBDフレームワークは、ステークホルダーのコンテキスト、動機、および具体的なニーズを理解することが、データを実行可能なインサイトに変換し、ビジネスを推進するために重要である。
  • 私たちのステークホルダーを支援するために、データの活用を推進し、より効率的なセルフサービスモデルを実現するべきである。これにより、ステークホルダーは自身の専門分野で最も得意なことに集中でき、データの整理に関する煩わしさから解放される。

感想

  • 事業会社のデータ部署に勤めている僕としては、めちゃくちゃ刺さりました。
  • JTBDを弊社なりに構築しつつ、もっとアナリストやDSと協働して、意思決定に刺さる指標がビジネスに素早く届けられるような状態を構築しなきゃなあ。
  • なぜ早くデータを出せるようにするのか、なぜメタデータを拡充するのか、なぜこのようなインターフェースを構築するのか、などをしっかりとビジネスインパクトと紐づけた上で、今後意思決定をしていけるようになれる気がしています!

Breaking the mold: A smarter approach to data testing(型破り:データテストに対するより賢明なアプローチ)

発表者:Anton Heikinheimo (Senior Data Engineer @ Aiven) , Emiel Verkade (Senior Analytics Engineer @ Aiven)

概要

僕たちはdbt testを書きまくっているけれど、デリバリーが遅くなることの方がデータ品質において深刻なケースが多いよね。
warningの利用やWHERE句による代替で不要なテストを消してデータ品質を向上させていこう

セッション内容の紹介

朝にSlackを開いて、dbtパイプラインのfailedの通知を確認して、トリアージを決めて、ステークホルダーと合意形成して、解決策を実装・テストしてデプロイする。そんな朝がたくさんあるのはおかしい。dbtのデータテストのベストプラクティスに従っているはずなのに

そんな言葉から始まった本セッションでは、以下のようなMEMEでテストを書くこととデリバリー品質の向上が一致しないことに対する課題感を説明していました。

現状のdbtテストを単純に実装していくと、以下のような課題点があると説明しています。

  • テストが落ちるとその下流のビルドがすべて落ちるので、データの品質が落ちる。
  • 特定のモデルが更新される一方で、他のモデルが更新されないことがありロジックによっては致命的である。
  • buildコマンドではテストは落ちるが、run → testの順番なのでrunによって不正なテーブルが出力される。

データテストが何であるか、そして典型的なデータセットアップがどのようなものか を以下の図を用いて説明していました。

この図における右と左のアサーションテスト(正常な場合に予測されるものと一致していることを確認するテスト)の役割を整理すると、以下のように記述できます。

  • 左側のアサーションテスト
    • ソースデータに関する仮定をテストするのに役立ちます。
    • このデータは、外部および内部のソースから来る可能性があり、データコントラクトやQAフレームワークが組み込まれていないこともあります。
  • 右側のアサーションテスト
    • 私たちが適用したロジックに関する仮定をテストするためのもの。
    • すでにソースデータをテストし、それが期待に合致していることを確認していると仮定しているもの。
    • 入力データが検証された後、出力データをテストすることで、私たちはロジックの整合性を確認できる。つまり、dbtプロジェクトで行ったすべての変換が、期待した結果をもたらすことを確実にするためのテスト。

例えば左側のアサーションテストで落ちた場合は図中の Data と記載されたテーブルに悪いデータが留まり、左のアサーションテストが解決されるまで更新されない ショートサーキット が発生します。

ただし、テストの重要性が不明瞭で、モデルのテストに対して厳しい要件を持つことでプロセスを標準化しようとしたり、テスターなどのメトリクスを持つことで対処しようとしたりする場合、テストが品質に与える影響を無視しているとも言えます。

上流のプロダクトやSaasの変化や変更は加速しており、テストは「そのテスト作成時点のアサーションでしかない」という主張です。なのでよく落ちるテストに対しては削除することが合理的な場合があり、落ちるケースに対しては以下のような対応をしてしまうとのことでした!

<= before | after =>

このようにフィルターとして扱ってしまうことで、テストによるデータ鮮度の品質を落とさず、そもそも間違ったデータが渡らないようにしてしまおうという発想のものです。

テストはデータ基盤のしなやかさを構築するためのものでもあり、そのためにSettleのチームではテストのデフォルトの重要度を「警告」に変更したとのことでした。確かにこのようにすれば、上流の変化に“しなやかに”対応しつつデータ鮮度の品質は落とさずにいられますね。

また、このテストではなくフィルターを記載する取り組みをスケールさせるために、マクロを使用していると話していました。

<= before | after =>

↑こんな感じでマクロを呼び出せるようにして、外部キー制約やaccepted_valueなどをフィルターとして表現可能にしているとのことです!

最終的に以下のようにテストを減らしつつ、しなやかな構成に変更できたと締めくくられています!

感想

  • 弊社もdbt + Lookerで構築されたセマンティックレイヤーがかなりのオペレーションに活用されており、こちらのパイプラインの停止がビジネスの停滞に繋がりうるため、とても参考になる発表でした!
  • 外部に公開する数字とか請求金額とか絶対に間違えちゃいけないもの以外は、実は多少ずれていても意思決定に大きく影響しないものもありますもんね!
  • 主キー制約とかまでフィルターでやっちゃうのは執念が感じられて笑っちゃったのと、弊社だとSalesforceみたいなデータソースの自由入力や意図しないデータ入力にパイプライン全体が影響を受けていたりするので、すぐにでも実践を検討したいです!

How dbt transformed FinOps cost analysis at Workday(訳:dbtがWorkday社のFinOpsコスト分析をどのように変革したか)

発表者:Eric PuSpeaker (Senior Software Engineer @ Workday), Pattabhi Nanduri ( FinOps Data Engineer @ Workday )

概要

DBTとJinjaマクロを活用してAWSやGCPを中心としたプラットフォーム上でのコスト要因を把握
DBTマクロやテンプレートを用いることで、ユーザーの負担を軽減し、データモデルの構築から実装までを自動化
モデル定義を通じて、ドキュメンテーションの自動生成やテストの自動実行

  • Workday社でのビジネス上の課題
    • コストとコストドライバーの理解: AWSやGCPから発生するコストやその要因を把握。
    • コスト最適化の機会の特定: コスト削減のための最適化ポイントを特定。
    • コストの割り当て:アプリケーションサービス、顧客、テナントごとにコストを適切に割り当て。
    • コストの予測:未来のコストを見積もり、予測する。
    • レポートとセルフサービス機能: 自己サービス型のレポート作成、チーム開発、行レベルアクセスやオブジェクトレベルアクセスなど、SOXコンプライアンスに対応したアクセス制御。
  • 作成したダッシュボード(写真撮り忘れました)
    • 今日の作業全体が表示され、コンピューティング、ストレージ、データベースなど、さまざまな支出の詳細が表示されているもの。同様に、月ごとのコンピューティングトレンドも表示されているもの。
    • コンピュータに関連する支出の詳細が表示されているもの。現在の四半期での使用状況を見ることができ、プロセッサやインターネット利用料などがわかるもの。
  • ダッシュボードのDimension
    • 階層型の製品Dimension
      • 最初のレベルでAWS製品とGCP製品といった大分類で区切り、7つのレベルにブレークダウンする形で分割しているもの。
    • 階層型のプロジェクトDimension
      • マーケットや人、組織に関する情報が含まれる。人と組織の情報は、プラットフォームの所有者や責任者に関連している。

全体のデータ構造はこんな感じです。

ユーザーが早い段階で次元カラムとファクトカラムを明確に定義するようにして、カラムのタイプを一度だけ定義すれば、その情報がデータマートの最終段階まで引き継がれるようにしているとのことです。 モデルの概要を宣言するだけで、残りのコードが自動的に生成され、モデルが正しく効率的に動作するように設計されています。

こちら紹介されていたサンプルクエリ。

lightdashを活用しているので、その辺りのアクセス制御もマクロを活用して行っているとのこと。

  • 動的なユーザーフィルター
sql_filter: {account_project_id in [select account_project_id from cpus.flops.access_control_bridge where login_user=${lightdash.attributes.user_name}]}
  • ユーザーアクセスコントロール
- name: effective_discount_column
  data_type: numeric
  meta: 
    dimension: 
      required_attributes:
        is_opus_super_user: "true"
- name: aws_cur_table
  meta:
    required_attributes:
      is_opus_super_user: "true"
  • このような構成にしたメリット
    • ユーザーに多くの教育を必要としない。
      • パーティショニングが自動で切られてテストも自動で追加されるため気にしなくても良くなる。
    • 統一された生成方法なのでドキュメンテーションが自動的に生成される仕組みを導入できた。
    • 情報をリネージグラフと組み合わせて、実行計画を作成し、それをAirflowに送信、実行計画に基づいて、Airflowはクラスタの動的スケーリングを行い、各ステージのワークロードに応じた最適なリソースの割り当てが可能。

感想

  • クラウド料金を探索できるデータモデリングをする際のDimensionの切り方や、主要なコストはそれ単体をFactとして切り出して名前をつけてしまっているところなんかが地味に参考になりました!
  • マクロ化には賛否色々ありそうですが、テストが自動で設定されるようになっていたり、DBTが生成するドキュメントに自動的に反映するような仕組みになっていたりして、ここまでやりきってしまえるならメリットが大きそうだなあと思いました!

Surfing the LLM wave: We can't opt out and neither can you(訳:LLMの波に乗る:私たちも、あなたも避けることはできない)

発表者:Amanda Fioritto(Senior Analytics Engineer @ Hex), Erika Pullum(Analytics Engineer @ Hex Technologies)

概要

データ分析&BI統合ツールのHexにできたmagicと呼ばれるLLMによるサポート機能をHex社自身が使い倒して
LLMによるクエリ生成の精度をどうしたらどのくらい向上させることができるか試行錯誤したレポートです

セッション内容の紹介

Hex社にはドッグフーディングの文化があるので、リリースした magic というLLMによるクエリサポート機能を自社でどこまで活用できるか常に使用してきたそうで、社内のmagic機能に「パトリック」という名前をつけているそうです!

パトリックの精度は論文やLLMモデルの公式発表などによると90%であるとのこと。

パトリックをオンボーディングする時の仮説

⇒ 人間の同僚とそれほど違わないかもしれない。

⇒ 人間のステークホルダーにとってデータが役立つように工夫することが、パトリックが新しい役割で成功する手助けにもなるかもしれない。

⇒ データ組織の役割はステークホルダーにとって使いやすいデータ資産を作ることであり、現在ステークホルダーにはパトリックも含めている。

パトリックの評価の比較対象はspiderというtext-to-sqlのオープンソースとのことです。

パトリックの評価を比較可能にするために「前四半期に予約された会議の数はいくつですか?」という質問を投げることにしたが

  • dim_dates というテーブルがJOINできていなかった。
  • 会議の日を特定するカラムを指定できていない。

など人間のステークホルダーからもよく寄せられる質問のようなミスをした。

「MMセグメントにいる顧客数は何人ですか?」という質問にパトリックが答えられるためには「顧客」とは何か、「セグメント」とは何を意味するのか、「MM」が何を指すのかを理解する必要がある。

パトリックのチューニング方法

  • 「エンフォースメント」というツールを使ってDWH内のアクセス範囲を拡げる、または狭める。
  • ドキュメンテーションへのアクセスを許可してカンニングペーパーありの状態にする。

アクセス範囲のチューニングの実験結果

  • アクセス範囲を全snowflakeテーブルに拡大 ⇒ 正答率10%
  • アクセス範囲をHex社内のテーブルに限定 ⇒ 正答率38%
  • アクセス範囲をHex社内のテーブルに限定して、よく使われるテーブルにフラグをつける ⇒ 正答率46%

ドキュメンテーションの実験をする際に、ドキュメントの品質にも差をつけた。

  • 低品質: segment_typeEnterpriseMid-Marketなどの値を含むことができる。
  • 高品質: 低品質なものに加えて同義語も提供します。例えば、「Small Midsize(中小企業)」は「SMB」とも呼ばれるし、「Mid-Market」は別の呼び方もある。

ドキュメントの品質によるチューニングの実験結果

  • 低品質のドキュメント ⇒ 正答率33%
  • 高品質のドキュメント ⇒ 正答率51%

セマンティックレイヤーを使った場合の実験結果

  • 正答率75~88%

実験結果を受けてHex社の見解

  • MMをMidMarketと変換できるような人なら、パトリックのサポートをうまく活用し、自分たちの作業を進められるかもしれません。
  • データチームにとって、これらのツールがどのように、そしてなぜ機能するのか、またそれが質問に答えようとする人たちにとって役立っているのかを理解することが重要です。
  • データウェアハウスの整理やモデルのドキュメント化やコンテキストの整理は必要です。
    • 重要なテーブルをマーキングする作業と高品質のドキュメント整備がそこまで差異がなかったのは驚異的でした。
  • LLMをうまくクエリビルダーとしてワークさせたいならセマンティックレイヤーの導入が必要そう。

感想

  • LLMをクエリビルダーとして使う想像は誰もがしたと思いますが、(僕も去年試行錯誤しましたhttps://speakerdeck.com/okodoon/slackkarazi-you-yan-yu-deshe-nei-zhi-biao-wowen-ihe-waserarerubotwozuo-ritaka-tuta)実際にこれをすると何%改善するのかというところまで定量的に示してくれている実例は滅多にないので素晴らしい発表だと思いました!
  • セマンティックレイヤーを作っていくことで、社内のクエリコスト低下だけでなくLLM活用まで見据えられそうなことが明確に示唆されたので、セマンティックレイヤー整備を引き続き頑張ります!
  • LLMをステークホルダーと捉えてマシンリーダブルなデータ基盤に寄せていくって発想は今後のデータ基盤にきっと求められていく要素なんだろうなあと思いました!

Semantic layers: The next data revolution or just overrated hype? (訳:セマンティックレイヤー:次のデータ革命か、それとも過大評価された流行か?)

発表者:Katie Hindson(Head of Product and Data @ Lightdash)

概要

dbtによってトランスフォーメーションが容易になったが課題が多く、数字の不整合の解消、指標の統一、LLMの活用といった課題を解決するためにセマンティックレイヤーが有用であると思われる。
ユニバーサルなセマンティックレイヤーを参照できるツール(Lightdash)がセマンティックレイヤーの活用方針としては望ましい

セッション内容の紹介

セマンティックレイヤー不在における課題点を以下のようなスライドで紹介しています。

  • クエリごとに同じ指標を出しているはずなのにバラバラになってしまう。
  • 指標の定義が社内で噛み合わない(アクティブユーザーのアクティブって何?「使用」の定義は?)
  • LLMをデータ基盤で活用するためには同じ質問に対して同じ答えが得られることが重要。

そして、今日のセマンティックレイヤーは以下のようにスタンドアロン型かバンドル型かに分類されるとの主張をしていました。

  • スタンドアロン型
    • ex. ATSCALE, Minerva, cube, dbt Semantic Layer
    • インテグレーションが不足しており、ビジネスユースケース足り得ない。
  • バンドル型
    • ex. Lightdash, MicroStrategy, Looker, SAP
    • BIツールに統合されたセマンティックレイヤー。他のモダンデータスタックとのインテグレーションが不足している。

セマンティックレイヤーの使用体験として必要なもの

  • メトリクスファーストの探索(テーブルを意識しないで指標名だけで思考が完結するような体験)。
  • データカタログでメトリクスの意味が確認できること。
  • データカタログから、簡単にメトリクスの探索ができること。

これらの体験を満たしているセマンティックレイヤーとして、Airbnb社が内製しているMinervaがとても優れていると述べていました。(Minervaに関するAirbnb社の記事はこちら

セマンティックレイヤーのユニバーサル性として必要なもの

  • スタック全体に適用できるほど汎用的
  • 必要なすべてのツールと統合可能

今後セマンティックレイヤーがデータ基盤の中心となるため、あらゆるデータスタックと接続可能な状態を構築する必要があるとのことでした!

感想

  • 結構ポジショントークみが強く「ユニバーサルって言葉をLightdashにだけ使うのは言葉として強すぎるのでは?」という指摘をQAで受けていて少し面白かったです。
  • Looker上にセマンティックレイヤーを構築している弊社としては、データカタログからの滑らかな探索体験みたいなところは実現が難しそうで、Lightdashも全然候補になってくるなと思いました!
  • Gemini on Lookerを超えるセマンティックレイヤー✖️LLMの体験を創出できるのか、これからもWatchし続けていきたいです。

【イベントレポート】タイミーのレコメンドにおける ABテストの運用

イベント概要

2024年9月18日に「GENBA #4 〜データサイエンティストの現場〜」と題してタイミー、ビットキー、AbemaTVの3社でデータサイエンスに関する合同勉強会を開催しました。 今回はそちらの勉強会からタイミーのデータサイエンティストである小関さん(@ozeshun_)の発表をイベントレポート形式でお伝えします。

続きを読む

Vertex AI Pipelinesを効率的に開発するための取り組み(part2)

こんにちは、タイミーのデータエンジニアリング部 データサイエンス(以下DS)グループ所属のYukitomoです。

DSグループではMLパイプラインとしてVertex AI Pipelinesを利用しており、その開発環境の継続的な効率化を進めていますが、今回はここ最近の変更点を紹介したいと思います!

Vertex AI PipelinesについてはGoogle Cloudの公式ページや、前回の記事を参照ください。

モノレポ環境に移行

当初はパイプライン毎にレポジトリを用意していました。しかしながら新規でパイプラインを起こす度にレポジトリの作成から行うのは、

  • ちょっとした“作業”ではあるのですが気軽に行うには少し腰が重い
  • cookie cutter を使って初期状態を揃えたり前回の記事のような標準化を行っても、異なるレポジトリを異なる開発者によりメンテナンスを行うと、それぞれが独自の進化をしたり属人化したりしがち

といった問題を抱えていました。そこで、モノレポ化して1箇所に集積し、

  • CI/CDや、パイプラインビルド等の付随スクリプトを共用化、付随スクリプトのような非本質的な機能開発を効率化
  • フォルダ構成やファイルの命名規則などを統一、“隣のプロジェクト”を参照しやすくすることで、ベストプラクティスを共有化、パイプラインの機能そのものの開発を効率化

することを目指しました。同一レポジトリ傘下に収めることで従来よりも敷居が下がり、共通知化を進められていると感じています。

コンテナイメージの共通化

パイプラインを1箇所のレポジトリに集めた段階でパイプラインのコンポーネントは200個以上あり、パイプラインのコンポーネントそれぞれが独自にDockerfileやpyproject.tomlを持っていました。脆弱性対応や機能追加のための依存モジュールのアップデートはそれぞれのpyproject.tomlを更新することになりますが、ファイルの数が多いと更新に手間がかかってしまいます。そこで、同一パイプラインのコンポーネント間ではコンテナイメージを共用できるような形にアーキテクチャを改めました。

おおまかな方針は以下のとおりです。

  1. コンポーネントの入出力を定義するyamlファイル(component.yaml)はそれぞれ名前を変え、1つのフォルダにまとめる。
  2. コンポーネントの中のロジックを記述するpython コードも1箇所にまとめ、全体をコンテナイメージに複製。
  3. 単一コンテナだけでは処理しきれない場合を考慮し、複数のコンテナイメージを格納できるようコンテナイメージ用のフォルダは階層化。

従来のアーキテクチャ

% tree PIPELINE_X

./PIPELINE_X
├── components
│   ├── component_A         # コンポーネント毎にフォルダを用意し、
│   │   ├── Dockerfile      # Dockerfile/pyproject.tomlはそれぞれ独立に配置
│   │   ├── component.yaml
│   │   ├── pyproject.toml
│   │   └── src
│   │       └── ...
│   ├── component_B
│   │   ├── Dockerfile
│   │   ├── component.yaml
│   │   ├── pyproject.toml
│   │   ├── src
│   │       └── ...
│   └── component_C
│       ├── Dockerfile
│       ├── component.yaml
│       ├── pyproject.toml
│       ├── src
│           └── ...
└── pipelines
    └── main.py 

新しいアーキテクチャ

% tree ./PIPELINE_X

./PIPELINE_X
├── components
│   ├── definitions           # 1. component.yamlは1箇所に集約
│   │   ├── component_a.yaml
│   │   ├── component_b.yaml
│   │   └── component_c.yaml
│   └── src                   # 2. src以下全てをコンテナイメージに複製.
│       ├── component_a.py    # component_*.yamlの設定で動作するpython fileを指定
│       ├── component_b.py    # DockerfileのCMDを指定するイメージ
│       └── component_c.py
│
├── containers                # 3. 単一コンテナでは難しい場合に備え
│   └── main                  # 複数のコンテナを利用できるようフォルダを階層化
│       ├── Dockerfile
│       └── pyproject.toml
└── pipelines
    └── main.py

コンテナ数を減らすことで、dependabotの運用は格段に楽になりました。コンテナが減ることで警告の数も下がり、警告の数が下がることで更新の初動も取りやすくなるという好循環のおかげで、2024年10月現在、dependapotからの警告は画面のスクロールが不要な範囲にはおさまるようになってきました。

また、コンテナを集約する段階で気がついたのですが、いくつかのDockerfileの中で利用するpoetryのバージョンが古いままだったり、マルチステージのビルドが正しく行われていなかったりするものも少なからずありました。Dockerfileに限らずコードライティング全般に言えることですが、記述量は可能な限り少なくする方が、このような小さな不具合の発生は抑制でき、安定したコードを供給できます。

CDにおけるビルドキャッシュの利用

タイミーDSグループにおいて、CI/CD環境はGitHub Actions、クラウド環境はGoogle Cloudを利用しています。指定されたトリガー条件が発生した時にコンテナイメージをビルドするのですが、GitHub Actionsの場合、ジョブ単位でVMが異なるため、連続するGitHub Actionsの実行の場合でもdockerのビルドは一からやり直しになってしまいます。 そこで、こちらこちらの内容を参考に、ビルド結果をVMの外部、Artifact Registryにキャッシュ、次回実行時に再利用することでCI/CD の処理を高速化させました。なお、以下の設定ではbuildcacheは通常のコンテナ用Artifact Registry(下のコードで言うと${IMAGE_NAME})とは異なるRegistry( ${IMAGE_NAME}-buildcache )に保存しています。

GitHub Actions内での記述より抜粋

docker buildx create --name container --driver=docker-container

docker buildx build \
  --builder=container \
  :
  --cache-from=type=registry,ref=${IMAGE_NAME}-buildcache \
  --cache-to=type=registry,ref=${IMAGE_NAME}-buildcache,mode=max \
  -t ${IMAGE_NAME}:${IMAGE_TAG} \
  --load .
              
docker push ${IMAGE_NAME}:${IMAGE_TAG}

# -cache-from/-cache-toに指定するrefの値にsuffix '-buildcache'を付加し
# 本来のイメージとキャッシュイメージの置き場所を分離しています。

パイプライン命名規則の工夫

MLパイプラインを開発していると、

  • あるパイプラインを少しだけ変えたパイプラインを実現したい
  • Gitの別ブランチで管理すればいいんだけれど、比較しながらコード書きたい

といったケースはよくあると思います。簡単にこれを実現しようと cp -r でパイプラインを丸ごとコピーしたとしても、従来のアーキテクチャでは様々な設定(パイプラインの名前、参照するコンテナイメージの名前、バージョン情報)を書き換える必要があります。そのため、煩わしい作業が発生していました。また、それらの設定方法も統一が取れておらず、“微妙に”パイプライン毎に異なっていました。そこで、それらのバージョン情報以外の情報を全てパイプラインが保存されているフォルダのパス情報から取得するよう統一し、cp -r だけですぐにパイプラインの亜種が作成できるようにしました。

従来のアーキテクチャ

# 1. パイプラインの名前はパイプラインのpyproject.toml内のname属性や環境変数(dotenv)を利用
# 2. コンテナイメージの名前は コンテナイメージのpyproject.toml内のname属性を利用
# 3. Version情報:
#    パイプライン    -> パイプラインのpyproject.toml内のversionを利用
#    コンテナイメージ -> コンテナイメージのpyproject.toml内のversionを利用
 
. PIPELINE_X
├── components
:
│
├── containers
│   └── main
│       ├── Dockerfile
│       └── pyproject.toml    # 2 [tool.poetry].name    -> パイプラインの名前# 3 [tool.poetry].version -> パイプラインのversion
├── pipelines
│   └── main.py
├── .env.* (prod/stg/dev..)   # 1 パイプラインの名前は .envからやpyproject.tomlなど
└── pyproject.toml            #   各種のやり方が存在。
                              # 3 [tool.poetry].version -> コンテナイメージのversion

# Compile されたpipeline config抜粋
{
  :
  "deploymentSpec": {
    "executors": {
      "exec-comp_a": {
        "container": {
        :
          "image": "${GAR_REGISTRY_PREFIX}/blahblahblah:vX.Y.Z"
          # 2. コンテナイメージの名前"blahblahblah"はコンテナイメージのpyproject.tomlより
          # 3. コンテナイメージのVersion "vX.Y.Z"はコンテナイメージのpyproject.tomlより
        }..}..}..},
      :
  "pipelineInfo": {
    "name": "arbitrary_string"
    # 1. パイプラインの名前は
  },

# 注: ${GAR_REGISTRY_PREFIX} は Artifact Registry のアドレス

新しいアーキテクチャ

# 1. パイプラインの名前はRepository内のフォルダ位置を利用 (= ${SERVICE}-${PIPELINE} )
# 2. コンテナイメージの名前は "${パイプラインの名前}"-"${コンテナのフォルダ名}"
# 3. Version情報:
#    パイプライン    -> パイプラインのpyproject.toml内のversionを利用
#    コンテナイメージ -> パイプラインのversionを利用

SERVICE/**/vertex_ai_pipelines/PIPELINE_X  # 1 
├── components
:
│
├── containers
│   └── main                             # 2
│       ├── Dockerfile
│       └── pyproject.toml
├── pipelines
│   └── main.py
├── pyproject.toml
└── .env.* (prod/stg/dev..) 

# Compile されたpipeline configの一部を抜粋
{
  :
  "deploymentSpec": {
    "executors": {
      "exec-comp_a": {
        "container": {
        :
          "image": "${GAR_REGISTRY_PREFIX}/${SERVICE}-${PIPELINE_X}-main:vX.Y.Z"
        }..}..}..},
      :
  "pipelineInfo": {
    "name": "${SERVICE}-${PIPELINE_X}"
  },
  :
  
# 注: ${GAR_REGISTRY_PREFIX} は Artifact Registry のアドレス

ちょっとした変更ではあるのですが、新しいパイプラインを構築する際の初動を早くすること、また簡単にできることにより、新しい方式を試そうという心理的な敷居を下げることができていると考えています。

今回紹介した取り組み以外にも、Vertex AI Pipelinesに限らず効率化するための具体的なアイデアはいくつかあるのですが、プロダクションを動かしながら変更しており、障害の発生を抑えるためにも、一度に大きな変更は与えずステップを踏みながらMLOps基盤を理想の姿に近づける活動を続けています。

We’re Hiring!


タイミーのデータエンジニアリング部・データアナリティクス部では、ともに働くメンバーを募集しています!!

現在募集中のポジションはこちらです!

「話を聞きたい」と思われた方は、是非一度カジュアル面談でお話ししましょう!

PyCon JP 2024参加レポート

みなさんこんにちは。タイミーのデータエンジニアリング部 データサイエンスグループ所属の菊地と小関です。

2024年9月27日(金)、28日(土)に開催されたPyCon JP 2024に参加してきました。今回はPyCon JP 2024の雰囲気と、特に興味深かった&勉強になったトークセッションをいくつかピックアップしてお届けしようと思います!

PyCon JPとは

PyConJPは1年に1度開催されていて、今年はTOC有明コンベンションホールにて9月27日(金)、28日(土)の2日間にわたって開催されました。

概要については、PyCon JP 2024の「What is PyCon JP」をそのまま引用させていただきます。

PyCon JP は、Python ユーザーが集まり、Python や Python を使ったソフトウェアについて情報交換、交流をするためのカンファレンスです。 
PyCon JP の開催を通じて、Python の使い手が一堂に集まり、Python にまつわる様々な分野の知識や情報を交換し、新たな友達やコミュニティとのつながり、仕事やビジネスチャンスを増やせる場所とすることが目標です。

当日のタイムテーブルはこちらを参照いただければと思います。

PyCon JPの雰囲気

今年の参加者数は600名超で、日本国内のみならず、海外からの参加者も多く、非常に活気がありました。昼食についても様々な文化圏の方に配慮して用意されていた印象です。

また、企業ブースも多数出展しており、トークセッションで気になった企業様の発表内容を更に詳しく伺うことができました。スタンプラリーや書籍販売、Pythonに関する求人が掲載されている等、ビジネスチャンスを増やせるよう、非常に配慮された設計だったと感じています。

個人(菊地)的には、企業ブースにいたGrooveX社の「LOVOT」がとてもかわいかったです(写真を撮っていないのが心残りです…)。

特に興味深かった、勉強になったトークセッション

まず、小関が興味深かった&勉強になったトークセッションを紹介します。

FastAPIでのasync defとdefの使い分け

speakerdeck.com

このセッションでは、タイトル通りのFastAPIにおける実装方法の使い分けを、Pythonにおける並列処理・並行処理・非同期処理の性質を説明した上で解説しており、非常にわかりやすかったです。

要点は以下の通りでした。

  • マルチスレッド、非同期処理ともにI/Oバウンドな処理の場合に高速化が期待できるが、マルチスレッドはスレッドが増えるとスレッド切り替え分だけ処理速度が低下してしまう
    • つまり、スレッドが多くなるような処理だと非同期処理の方が処理速度が速くなる場合がある
  • Fast APIにおけるdefasync defの違いと使い分け
    • def
      • 並行処理 (マルチスレッド)
      • 同期処理を行いたい場合はこちらを使う
    • async def
      • 非同期処理
      • マルチスレッドだとスレッドの切り替え時間がかさむぐらいのリクエスト量をさばきたい時に有効

低コストで実現する社内文書RAG機能を搭載したAIチャットボット開発

speakerdeck.com

このセッションでは、RAG機能を用いたAIチャットボットの開発について、主に開発前の実装スコープの決め方や実装方法の詳細の観点からお話しされていました。

開発前にpros & consを言語化して、目的にあったHowとして今回のRAG + Chat botを選択した過程がわかりやすくまとまっていたり、システムのアーキテクチャ自体も丁寧に説明されていたりしたので、今すぐにでも社内で試せそうな感じでした。

弊社だとNotionのドキュメント量が膨大なので、indexingするドキュメントの選定基準をどう決めたのかが特に気になりました。Notionのページ階層が綺麗にまとまっている組織だとindexingする対象を選択する時の手助けになるのかなとも思いました。

LlamaIndexは未履修なので、近々個人で触ってみようと思います!

次に、菊地が興味深かった&勉強になったトークセッションをピックアップして紹介します。

PandasAI:生成AIがデータ分析業務にもたらすパラダイムシフト

speakerdeck.com

このセッションでは、機械学習・生成AI・データ分析の基礎の基礎を説明した後に、PandasAIについて紹介しています。

PandasAIとは、自然言語でデータ分析をしたり可視化を行ったりできるデータ分析のためのAIエージェントで、OSSとして公開されています。OpenAIのAPIキーがあれば使用できるとのことです。

また、SaaSとしても提供しており、登録・課金を行えばAPIキーがなくとも使用できるそうです。

データコネクタとしては、CSVやParquet, XLSX等はもちろん、PostgreSQL, MySQL, BigQuery, Databricks, Snowflakeといった各種クラウドサービスのデータソースへ接続できます。

内部の処理としては、自然言語をPythonコードやクエリに変換してデータを操作し、結果をユーザーへ返却しており、悪意のあるコードの実行に対する制御もできるそうです(ホワイトリストとして特定のモジュールのみ実行可能にする等)。

OSSとして提供されているので一度試してみたいなと思っているのですが、弊社でも導入しているLookerやその他BIツールに搭載されているAI機能とどのように差別化していくのかは気になりました。

データサイエンスのフルサイクル開発を実現する機械学習パイプライン

speakerdeck.com

このセッションでは、まずCARTA MARKETING FIRM社におけるデータサイエンティスト像「フルサイクルデータサイエンティスト」について紹介し、類似概念「フルスタック」との違いを説明しています。

その上で、理想状態とのギャップを課題として整理し、データサイエンティストがより本質的な価値創出ができる状態に向けて、これまでのデータ分析基盤の歴史(luigi → Amazon SageMaker → Prefect)が紹介されています。

タイミーのデータサイエンティストも「フルサイクルデータサイエンティスト」に近い働き方をしている点や、ML基盤の歴史が似通っていたり、チームの規模感や構成が近いなど、多くの共通点がありました。「わかる〜」と心の中でうなずきながら、セッションを聴かせていただいておりました。

あえてApache AirflowではなくPrefectを選定した経緯などは、機会があればぜひ伺ってみたいなと思いました。

終わりに

いかがでしたか?PyCon JP 2024の雰囲気が少しでも伝わっていますと幸いです。次回は広島開催とのことで、ぜひ来年も参加させていただきたいなと思っています。

ちなみに、タイミーには「TDE10」という、プロダクト開発やデータ職種メンバーを対象とした成長支援制度があります。今回は「世界中で開催されているすべての技術カンファレンスに無制限で参加できる『KaigiPass』」を利用してPyConJPに参加しました。

今後もこのような機会があれば、積極的に技術カンファレンスに参加していきたいと考えておりますし、外部登壇も積極的に行っていきたいです。

We’re hiring!!!

現在、タイミーでは、データサイエンスやエンジニアリングの分野で、共に成長し、革新を推し進めてくれる新たなチームメンバーを積極的に探しています!

また、気軽な雰囲気でのカジュアル面談も随時行っておりますので、ぜひお気軽にエントリーしてください。↓

product-recruit.timee.co.jp hrmos.co hrmos.co hrmos.co hrmos.co