DROBEプロダクト開発ブログ

DROBEのプロダクト開発周辺の知見や考え方の共有をしていきます

PHP Conference Japan 2023で登壇します

こんにちは。角田です。 DROBEは2023年10月8日(日)に開催される、PHP Conference Japan 2023で登壇します。

2000年より年に1回開催されている日本最大のPHPのイベントです。初心者から上級者まで幅広くたくさんの参加者が蒲田に集結します。今回の登壇もとてもバラエティに富んだ内容になっており、あと数日ですがワクワクが止まりません!

登壇内容

『25分で理解する!Symfonyの魅力とその実践的活用法』というタイトルで、Symfonyの魅力についてお話ししていきたいと思います。限られた時間ですが、しっかりお伝えできればと思います。

fortee.jp

ブース出展もします

今回はゴールドスポンサーとして協賛しており、ブースも出展いたします。ブースにお越しの方にはプレゼントをご用意しております。 登壇後のご質問などにもお答えできると思いますので、ぜひお立ち寄りください!

PHP Conference Japan 2023について

phpcon.php.gr.jp

Vision-Language Modelsを使った商品のトップ画像選定

 

DROBEで機械学習エンジニアをしております、藤崎です。

背景

商品のトップ画像はユーザーへの最初のタッチポイントとして機能し、購入を促進します。そのため、適切なトップ画像の選定は重要です。しかしながら、この選定は現在、手動に依存しており、複数の商品画像から最も効果的なものを選ぶ作業は、多大な時間と労力を消費しています。

商品の品揃えが拡大する中で、この作業のコストは切実な課題となっています。そこで、機械学習技術を用いてトップ画像の選別を自動化するアプローチを検討しています。これにより、商品登録時間の削減や業務の効率向上が期待されます。

本記事では、商品のトップ画像の自動選別に焦点を当て、画像分類手法を調査します。これにより、商品のトップ画像の自動選定を効果的に実行し、効率と精度を同時に向上させることを目指します。

結論

  • 本タスクでのVision-Language Modelsでの画像分類の性能は低かった。
  • Promptは長い文章とした方が性能が良いことが示唆された。
  • 統計量に注目することで、分類が困難な場合を特定できそうなことが示唆された。
  • Vision-Language Models + 単純な分類モデルで誤分類が少ない推論パイプラインの有望性が示唆された。

手法の検討

商品のトップ画像の選別は分類タスクなので、これを実現する手段としては、教師あり学習や基盤モデル(Vision-Language Models)がざっと候補に上がると思います。

教師あり学習は、学習段階で画像に対応したクラスラベルを用いてモデルを訓練します。このモデルは、推論段階で新たな画像が与えられた際に、学習時に設定されたクラスの中から、その画像が属する最も可能性の高いクラスを予測します。

一方、Vision-Language Modelsは、画像とテキストを同時に解析し、これらの複数のモダリティ間の関係を評価する能力を持つモデルです。このモデルを利用すると、特定の画像に対して複数の自然言語文を提示し、それぞれの文が画像とどれだけ類似しているかを判定することが可能になります。これにより、コンテキストに富んだ分類が実現できます。これは、教師あり学習があらかじめ設定されたクラスラベルを基に分類を行うのに対して、Vision-Language Modelsは、より動的で柔軟な分類手法であるという特長があります。

教師あり学習や基盤モデル(Vision-Language Models)のそれぞれの特徴はざっと以下のように認識しています。

  精度 データ作成コスト Zero-shot性能 デプロイコスト 推論コスト
教師あり学習(ex. ResNet, ViT) 中 ~ 高
基盤モデル(Vision-Language Models) 中 ~ 高

それぞれの列の説明としては以下のとおりです。

  • 精度: モデルが分類タスクをどれだけ正確に実行できるか。
  • データ作成コスト: 訓練データを収集、整理、アノテートするのに必要なコスト。
  • Zero-shot性能: 未見のデータに対してモデルが発揮できる精度。
  • デプロイにかかるコスト: モデルを実際の環境にデプロイするための時間的、金銭的コスト。
  • 推論コスト : 推論にかかる金銭的なコスト。

上記表のポイントとして、

教師あり学習モデルは一般に高い精度を達成することが期待できます。しかしながらZero-shot性能に制限があるため、特定のタスクに特化させるためには自社でデータを収集・整理し、モデルを学習する必要がありコスト(時間的、金銭的)がかかる可能性があります。

一方、Vision-Language Models(基盤モデル)の場合、教師あり学習モデルに比べて精度が若干劣る可能性はありますが、Zero-shot性能に優れているという利点があります。これは、公開されているモデルをそのまま使用しても、多様なタスクに対してある程度の性能を発揮するため、データの収集とアノテーション、モデルの学習といったコスト(時間的、金銭的)を節約できる可能性があると考えています。

そのため、今回はより実用性の高いVision-Language Modelsを対象に実験しました。

実験

実験概要

今回はVision-Language Modelsのうち、GCPのMultiModalEmbeddingModelを使用しました。

分類モデルの基本的な処理の流れは以下のとおりです

    1. 候補となる全ての  prompt \in P のembeddingを作成する
    1. ある画像  image \in I のembeddingを作成する
    1. 1)と2)の内積をとり、argmaxを計算する。
    1. ある画像  image \in I のクラスが確定する

ここで、 prompt とは教師あり学習の枠組みでいうところのクラスを指し、今回の設定では具体的に以下のようなものを指します。

  1. 該当画像はモデルがアイテムを着用し、全身が写っている画像か?
  2. 該当画像はモデルがアイテムを着用しているが、モデルの体の一部しか映っていない画像か?
  3. 該当画像はアイテムのみが写ったモデルが着用していない、物撮りの画像か?

実験では約900画像に対して推論し、その性能を評価しました。

実験1 : 単純なPromptを投げる

素朴に、 prompt を以下とし、評価しました。

(このpromptはGPT-4が作成しました。)

  内容 prompt
#1 モデルがアイテムを着用し、全身が写っている画像か? The entire human body from head to toe is captured in the image.
#2 モデルがアイテムを着用しているが、モデルの体の一部しか映っていない画像か? Only a part of the human body is captured in the image.
#3 アイテムのみが写ったモデルが着用していない、物撮りの画像か? No human is captured in the image.

結果は以下の通りです。

  mean accuracy mean precision
試行1 0.46 0.39

ここで、

  • mean accuracyは複数のクラスがある分類タスクにおいて、それぞれのクラスでの正確さ(accuracy)を平均した値です。
    • また、accuracy とは各クラスでの正解数をそのクラスのサンプルの合計数で割った値です。
  • mean precisionは各クラスにおいて計算された適合率(precision)を平均した値です。
    • また、precision とは正と予測されたサンプルのうち、実際に正であったサンプルの割合です。

この結果を見ると性能はあまりよくないことがわかります。

以下らについてもう少し深掘りしてみます。

  • promptの分量の精度への影響
  • 間違った場合の考察

実験2 : Promptを工夫してみる

promptの分量の精度への影響について見てみます。

もしかしたら文章ではなくキーワードだけの方が性能が高いかもしれませんし、あるいは反対に長文にした方が性能が高いかもしれません。

promptは補足に掲載しますが、結果は以下の通りでした。

試行1 : ベースライン

試行2 : ベースラインからキーワードだけ抽出したもの

試行3 : ベースラインを長文化したもの

試行4 : ベースラインを長文化し、キーワードだけ抽出したもの

試行5 : 試行4のprompt間で意味が重複したキーワードらを排除したもの

  mean accuracy mean precision
試行1 0.46 0.39
試行2 0.15 0.43
試行3 0.64 0.32
試行4 0.69 0.39
試行5 0.22 0.28

この結果を踏まえると、promptにはなるべく多くのキーワードを盛り込んだ方が良さそうということがわかります。

しかし、ここで最もaccuracyが高い試行4ではpromptの中身をよく見てみると、異なるprompt間で似たキーワードを含んでいました。

そのため試行5では、そのような意味が重複した単語を排除しました。ただ不思議なことにこの試行では性能が大きく下がるという結果になっています。

実験3 : 間違った分類を回避するには?

ここで間違った問題についてもう少し深掘りしてみます。

仮説として、正解する場合は自信を持って正解するということです。すなわち以下の3)で特定のクラスだけ相対的に大きい値となることです。

逆に正解する場合は全てのクラスが同じような値になるのではないかということです。

    1. 候補となる全ての  prompt \in P のembeddingを作成する
    1. ある画像  image \in I のembeddingを作成する
    1. 1)と2)の内積をとり、argmaxを計算する。
    1. ある画像  image \in I のクラスが確定する

この差異は標準偏差で炙り出せるのではないでしょうか。

すなわち、正解する場合は標準偏差が大きく、失敗する場合は標準偏差が小さくなるということです。

実際に計算してみます。

  mean accuracy mean precision 正解した場合の3)工程での標準偏差 失敗した場合の3)工程での標準偏差
試行1 0.46 0.39 0.00421 0.0043
試行2 0.15 0.43 0.00719 0.00601
試行3 0.64 0.32 0.00463 0.00373
試行4 0.69 0.39 0.00616 0.00594
試行5 0.22 0.28 0.00513 0.00547

計算の結果、有望な性能を示したケースでは、正解時の3)の工程での標準偏差が、失敗時に比べて大きくなる傾向が確認されました。

試行4のデータについて頻度分布をヒストグラムで可視化し、分布の特徴を詳しく分析します。もし、正解と失敗の分布がはっきりと乖離している場合、特定の標準偏差を閾値として採用し、その閾値を下回る場合には、その画像の分類を避けるアプローチが有効であると考えられます。

 

試行4の標準偏差のヒストグラム

しかし、ヒストグラムの解析結果から、二つの分布がある程度重複していることが確認できます。これは、単純な閾値設定による分類の制限が難しいことを示唆しています。

それでも、3)工程の出力をもとに、「分類が成功するか、失敗するか」を判定する2値分類タスクを考えました。この方法により、分類が困難なケースを特定し、それらのケースに対する推論を避ける、あるいは特別に処理するという戦略を採用できます。

この分類モデルとしてXGBoostを使った2値分類タスクの結果は、accuracyが0.79、precisionが0.81となりました。これにより、分類が困難なケースを特定し、それを回避または別途処理できる可能性が示唆されます。言い換えると、特定の画像が誤分類される可能性を事前に排除または低減できる可能性があるということです。

Vision-Language Modelsによる分類が信頼できそうかを判定する分類モデルを活用した場合の処理の流れ

 

まとめ

今回の分析から、Vision-Language Modelsを単独で用いた場合には、今回の設定では実用的に使えないという結論になりました。しかし、性能向上の余地が存在することも明らかになりました。

例えばpromptの工夫や最適化によって、モデルの性能向上が期待されるということです。特に、promptの長文化(具体性の向上)によって、より適切な画像分類が可能となることが示唆されました。

さらにVision-Language Modelsを他の分類モデルと組み合わせて使用するアプローチも有望です。これにより、全体として誤分類のリスクを減少させることが可能です。

引き続き、これらのアプローチを深掘りし、検証を進めていく予定です。

参考文献

補足

- 実験2で用いた  prompt (このpromptはGPT-4が作成しました。)

  内容 prompt(試行1) キーワード(試行2) 長文prompt(試行3) キーワード(試行4) キーワード(試行5)
#1 モデルがアイテムを着用し、全身が写っている画像か? The entire human body from head to toe is captured in the image. entire body, head to toe, captured The image features a person fully dressed, providing a complete view of the attire from head to toe. All clothing items and accessories are clearly visible, offering an all-encompassing look at the fashion style. This allows for an in-depth analysis and categorization of the overall outfit, including design, color schemes, and combinations. person fully dressed, complete view, head to toe, clothing items, accessories, visible, fashion style, in-depth analysis, categorization, design, color schemes, combinations complete view, head to toe, fashion style, in-depth analysis, color schemes, combination
#2 モデルがアイテムを着用しているが、モデルの体の一部しか映っていない画像か? Only a part of the human body is captured in the image. part of body, captured In this image, attention is given to a specific part of the body and attire. The focused view presents detailed features of the clothing, including fabric, design, and accessories. This partial display aids in a concentrated analysis, enabling categorization based on the distinct visible elements. specific part of body, focused view, detailed features, clothing, fabric, design, accessories, partial display, concentrated analysis, categorization, visible elements specific part of body, detailed features, fabric, concentrated analysis, visible elements
#3 アイテムのみが写ったモデルが着用していない、物撮りの画像か? No human is captured in the image. no human, captured This image contains no human subject, featuring only clothing and accessories. The absence of a person allows for an unobstructed view of the attire’s design, texture, and style. It facilitates a straightforward classification of the clothing items, free from the influence of human form and posture. no human subject, clothing and accessories, unobstructed view, design, texture, style, straightforward classification, free from human form and posture no human subject, unobstructed view, texture, style, free from human form and posture

 

- 試行4での失敗例の画像

以下らの画像は 物撮りの画像(=人が写っていない) と分類されてしまいました。

(著作権の関係で画像を削除しました。編集 : 2023/10/04)

 

GPT-3.5-turbo を Fine-tuning して GPT-4 相当の性能を獲得する

はじめに

こんにちは、DROBE の都筑です。

みなさん LLM 使っていますか。今回は GPT-3.5-turbo の Fine-tuning の事例を紹介します。

結論

  • GPT-4 を利用して得られたデータを使って GPT-3.5-turbo を Fine-tuning する事で、特定のタスクに関しては GPT-4 相当の性能が出る事が確認できた
  • GPT-4 利用時点で使っていたプロンプトをそのまま使った場合の性能が一番高く、token 節約のためにプロンプトの省略をすると性能が劣化した

背景

LLM を利用したサービスの開発において、OpenAI を利用する場合にはモデルの選択肢がいくつかあります。2023年9月現在では、GPT-4 と GPT-3.5-turbo が主な選択肢になると思います。

ばっくりとは、性能が高いが価格が高くて応答速度と Rate Limit の面で取り扱いが難しい GPT-4 と、性能がそこそこだが価格が安くて応答速度が早く Rate Limit に余裕のある GPT-3.5-turbo という考え方になるため、性能が許す限り GPT-3.5-turbo を使うというのが基本戦略になります。

name 性能 価格 応答速度 Rate Limit
GPT-4 高い 高い 遅い 厳しい
GPT-3.5-turbo そこそこ 安い 早い 緩い

課題

DROBE では非構造化データを解析して情報を抽出する事に LLM を利用しようと考えていました。以下のような条件のタスクになりす。

  • Input: ~ 3000 token
  • output: ~1000 token
  • 実行したいタスクの数: ~4000/day 程度

このタスクをまずは GPT-3.5-turbo で解こうと考えましたが、抽出された情報の精度という意味で、性能が思うように出せませんでした。一方で GPT-4 であればある程度納得感のある性能が出せる事が確認できました。

タスクとしては 1600万 token /day 程度の token 数を前提としておいているので、24 時間以内にタスクを完了させるためには TPM (token per minutes) に直すと約 11111TPM 程度の性能が必要になります。

GPT-4 の Rate Limit はアカウントによって違いますが、 20000 TPM が許されているアカウントを例に計算すると、以下のような制約があります。

  • 実行時間
    • 20000 TPM を無駄なく(待ち時間などなく)利用したとして、約 13 時間掛かる
  • Rate Limit
    • api 呼び出しで 1 分間に 20000 token 以上のリクエストを行うとエラーになってしまうため、api 呼び出しの間で wait time を設けるなどの工夫が必要になる
  • 金額
    • $600/day (月間 72 万円程度と) と非常に高額になる

ここで、金額計算の根拠は以下になります

$600 = ((0.00003($/token) * 3000(token) * 4000) + (0.00006($/token) * 1000(token) * 4000))

こういった課題感から GPT-4 の性能を GPT-3.5-turbo で獲得できないかを試すために Fine-tuning を試す事にしました。

Fine-tuning とは?

OpenAI の model における Fine-tuning とは、追加での学習をさせる事で様々なタスクでの性能向上させる事ができる手法です。

Fine-tuning improves on few-shot learning by training on many more examples than can fit in the prompt, letting you achieve better results on a wide number of tasks

具体的には FIne-tuning 用のデータを準備した上で OpenAI の API を叩く事で作成する事ができます。

Fine-tuning のユースケースは公式にも乗っていますが、その中で興味深い一文があります。

Another scenario where fine-tuning is effective is in reducing costs and / or latency, by replacing GPT-4 or by utilizing shorter prompts, without sacrificing quality. If you can achieve good results with GPT-4, you can often reach similar quality with a fine-tuned gpt-3.5-turbo model by fine-tuning on the GPT-4 completions, possibly with a shortened instruction prompt.

GPT-4 で良い結果が得られるのであれば gpt-3.5-turbo モデルを GPT-4 の結果で Fine-tuning する事で同等の性能が得られる可能性がある、という記載があります。

Data の準備

データを準備するために、まずは機能を作り GPT4 で数日程度稼働させます。この期間は応答速度も遅い上に金額も高いですがデータの取得期間という事で割り切って機能を稼働させます。

具体的には以下のような形で Lambda で GPT-4 を叩きつつ、入力と出力のペアを json 形式で Cloudwatch に落とします。

Fine-tuning するためのデータ取得

{
  "input": "input text",
  "output": "output text"
}

データが集まったら、以下のようなコマンドで Cloudwatch のデータを手元に落とします。(以下のコマンドは Mac での動作を前提にして gdate に依存しているので環境に合わせて適宜修正してください)

aws logs filter-log-events \
--region ap-northeast-1 \
--log-group-name <log-group-name> \
--start-time `TZ=Asia/Tokyo gdate --date='2023-09-01 00:00:00.000' +%s%3N` \
--end-time  `TZ=Asia/Tokyo gdate --date='2023-09-10 00:00:00.000' +%s%3N` > fine-tuning-data.log

データをダウンロードしたらここを参考に Fine-tuning のデータの準備と validation を行います。

github.com

Fine-tuning 用のデータは jsonl 形式のデータになります。Fine-tuning する際の最大 token 数は 4096 で、それ以上は勝手に truncate されてしまうので、実施前にデータの token 数をカウントする事が推奨されています。

データを準備できたら Training 用のデータと Test 用のデータに分離しました。Test 用のデータは Training には使用せず、Fine-tuning されたモデルでタスクを実行してみて結果が同じになるかどうかを試してモデルの性能を評価するために利用します。

Fine-tuning を実施

Fine-tuning の実施は簡単です。OpenAI の API を利用して以下を実施します。

  1. トレーニングデータをアップロード
  2. アップロードしたデータを指定しつつトレーニングを開始

DROBE では以下のスクリプトを GitHub Actions で実施しました。

# Upload data
file_response = openai.File.create(
    file=open("<path-to-file>.jsonl", "rb"), purpose="fine-tune"
)

# Get the file ID
file_id = file_response["id"]

# Check the file's status
status = file_response["status"]
while status != "processed":
    print(f"File status: {status}. Waiting for the file to be processed...")
    time.sleep(10)  # Wait for 10 seconds
    file_response = openai.File.retrieve(file_id)
    status = file_response["status"]

# Create the fine-tuning job using the file ID
if status == "processed":
    fine_tuning_response = openai.FineTuningJob.create(
        training_file=file_id, model="gpt-3.5-turbo"
    )
    fine_tuning_job_id = fine_tuning_response["id"]  # Store the fine-tuning job ID
else:
    print(f"File processing failed with status: {status}")

print(f"Fine-tuning job created with id: {fine_tuning_job_id}")
fine_tuning_job_response = openai.FineTuningJob.retrieve(fine_tuning_job_id)
fine_tuning_job_status = fine_tuning_job_response["status"]

while fine_tuning_job_status != "succeeded":
    print(
        f"Fine-tuning job status: {fine_tuning_job_status}. Waiting for the fine-tuning job to complete..."
    )
    time.sleep(10)  # Wait for 10 seconds
    fine_tuning_job_response = openai.FineTuningJob.retrieve(fine_tuning_job_id)
    fine_tuning_job_status = fine_tuning_job_response["status"]

print(f"Fine-tuning job completed with status: {fine_tuning_job_status}")
print(f"Fine-tuned model id: {fine_tuning_job_response['fine_tuned_model']}")

結果

Fine-tuning が完了したら、そのモデルを利用して事前に準備しておいた Test データに対してタスクを実行します。

その際に以下のような事を検証しました。

  • プロンプトは GPT-4 で利用していたものと完全に同じにする
    • ただし実験として、プロンプトを省略したものも同時に実施しました
  • few-shot learning に対してどれくらいの精度向上が見られるかを試す

結果としては以下のようになりました。

  • Fine-tuning すると結果が GPT-4 に近づく事が観測できた
    • 100 data よりも 500 data の方が性能が向上した
    • 500 data で Fine-tuning した場合には 84% が GPT-4 の結果と完全一致した
  • Fine-tuning しても prompt を削ると性能が悪化した
  • 比較のため gpt-3.5-turbo-16k-0613 を few shot したものも入れた
    • few shot なしよりも性能が向上したが、fine tune したものには及ばなかった
    • fine tune したモデルは現状 4k token max なので few shot は出来なかった

success の定義は GPT-4 での結果と GPT-3.5 の結果が完全一致としています

model finetune prompt few-shot success succes_rate
gpt-3.5-turbo-16k-0613 no オリジナル なし 20/50 0.4
gpt-3.5-turbo-16k-0613 no オリジナル あり 25/50 0.5
gpt-3.5-turbo 100 data オリジナル なし 39 / 50 0.78
gpt-3.5-turbo 100 data 簡略版 なし 27 / 50 0.54
gpt-3.5-turbo 500 data オリジナル なし 42/50 0.84

おわりに

GPT-4 での推論のデータを利用して GPT-3.5-turbo を Fine-tuning してみた事例を紹介しました。想像していたよりも性能の向上が出来て驚きました。

他にタスクにも利用できるのではないかなと考えているので、さらに色々と試してみたいと考えています。

参考

platform.openai.com

platform.openai.com

DROBE Engineer Night #5 "質とスピードを追求する開発チームでの取り組み" を開催しました

こんにちは。DROBEの角田です。

2023年9月5日に、DROBEが主催するテックイベント『DROBE Engineer Night』の第5回を開催しました。今回は、"質とスピードを追求する開発チームでの取り組み" というタイトルで、株式会社リンケージ・ピクシブ株式会社と弊社の3社合同で開催しました。

drobe.connpass.com

現地・オンラインとも非常にたくさんの方にお越しいただき、盛況な会となりました。

弊社からは、『素早いバリュー提供のための
DROBEの新戦略』というタイトルで、現在行なっている顧客へ素早く価値を届ける試行錯誤についてご紹介させていただきました。

speakerdeck.com

リンケージさん・ピクシブさんには非常に積極的にご協力いただき、発表内容も開発・本番環境の差分を減らすであったり、防火壁を持つという考え方など、弊社にも取り込める内容が散りばめられた素敵なお話で、大変参考になりました。ありがとうございました。

今後も定期的にテックイベントを開催し技術的な発信をしてまいりますので、ご期待ください!

LLM で長文から構造化データを抽出する

はじめに

こんにちは、DROBE の都筑です。

みなさん LLM 使っていますか。今回は LLM を利用して長文から構造化データを抽出する手法について記載します。

構造化データの抽出

LLM を利用して構造化データを抽出することを Extraction と呼びます。 Extraction は以下のようなユースケースが考えられます。

  • テキスト情報から構造化したデータを抽出し DB にインサートする
  • 外部 API を呼ぶために入力を解釈してパラメータを抽出する

Extraction は非常に有用ですが、元となるテキストの最大長は利用する LLM の最大 token 数に依存します。

LLM と長文の処理

長文を LLM で扱うユースケースとしては文章要約がアプリケーションとして想定されることが多く、いくつかの方法が考案されています。LangChain の公式ドキュメントを覗くと、以下の 3 つの手法が提案されていました。

  1. Stuff

  2. Map-Reduce

  3. Refine

1 つめの Staff とは単純に全入力を LLM に突っ込むという手法です。2023年9月現在、最も手軽に使える OpenAI の gpt3.5-turbo では最大 16k token が使えるのでそれで充分であれば特に難しいことを考える必要はありません。また anthropic 社の Claude2 など 100k token に対応しているモデルも登場しており、近い将来 token の事を気にする必要はなくなりそうです。

2 つめの Map-Reduce は、入力をチャンクに分割しそれぞれに対して要約、最後に全ての要約を入力として一つの要約に纏めるというものです。Map-Reduce という名前でピンとくる方もいると思いますが、この手法は処理を並列化できて後述の Refine に比べて高速に動かすことが出来るという利点があります。

3 つめの Refine は、入力をチャンクに分割し、順番に要約をしていくのですが、最初のチャンクの要約を次のチャンクの要約時に入力として一緒に与えてあげるということをします。この手法では直前のチャンクの要約結果を待たないと次のチャンクの要約を行えないので処理を並列化することが出来ずに遅くなりますが、Map-Reduce に比べて内容をより正確に要約できるとのことです。

長文データから構造化データを抽出する手法

DROBE では長文のデータからタグを抽出して DB に保存する、というタスクを行おうとしていますが、LangChain の思想を参考にして以下のようなデータパイプラインを設計しました。

長文データからの抽出タスクパイプライン

以下が大まかなステップです。

  1. 文章をチャンクに分割する
  2. 分割された文章からタグを抽出する
  3. 抽出されたタグをマージしユニークな配列にする

最初のステップとして長文のデータをチャンクに分割していますが、これにより token 数がすくない LLM でも情報の抽出が可能になります。チャンクへの分割は一見簡単なように見えて難解なトピックです。一般的には以下のような挙動が期待されます。

  1. 文章の意味が失われないように分割を行う
  2. 分割されたチャンクを指定したサイズを超えるまで結合していく
  3. チャンクが指定サイズに達したら、次のチャンクを作る

この処理は、日本語の場合はなかなか難しい問題です。普通に実装する難易度が高いと考え、今回は Text Split は gpt3.5 にやらせることにしました。精度の必要なタグの抽出は gpt4 にやらせ、分割はより多くの token を扱える gpt3.5 で行うといった工夫です。

ちなみに、LangChain では TextSplitter というクラスが用意されています。

python.langchain.com

実装を覗いてみると、正規表現などを使った Splitter の他に、 all-mpnet-base-v2 model を利用した splitter も準備されていました。

huggingface.co

英語であれば LangChain が準備してくれている Splitter を使ってみると良さそうに思いました。

おわりに

長文のデータから構造化データを取得する方法を紹介しました。LLM の進化によりこういった手法などはいずれ必要なくなると考えていますが、現時点ではまだまだ扱える token サイズに制限があるためにこういったやりかたを考える必要があります。同じように困っている方の参考になれば幸いです。

参考

Extraction | 🦜️🔗 Langchain

Summarization | 🦜️🔗 Langchain

SAチーム化も見据え開発チームにLeSSを導入したはなし

はじめに

EMの加川(@shinpr_p)です。
ここ数週間で、DROBEの開発チーム体制に変化がありました。今回は体制変更の背景や考慮した事、どのようにチーム体制を考えたかを記事にしてみました。
チームを取り巻く状況によって選択肢は異なりますが、1つの事例としてチーム体制の参考となれば嬉しいです。

※ 余談ですが、この文章は社内向けに体制変更を説明した際に書いたものとある程度同じ内容になっています。

体制変更の背景

現在のDROBE開発チームは、組織観点においてふたつの課題を抱えています。

ひとつは、開発チームメンバーの多さです。

全員が集まるMTGとなると参加者が10名を超えてきます。10名を超えるとコミュニケーションパスが複雑になり過ぎ、性質に依らず話しづらさを感じたり話さなくなったりする人が出てきます。この状態はスクラムの三本柱である「検査」「適応」「透明性」が損なわれることを意味し、課題発見の遅延によってアジリティが失われてしまいます。

参考: ミラーの法則

makitani.net

もうひとつは、開発チームが関心を持つ責務領域です。

注力するビジネスミッションが複数ありそれぞれに担当PdMが存在するが、開発チームはひとつである。プロダクトは事業全体に関係するが、ビジネスミッションの集合では事業全体をカバーできない(取捨選択の観点で意図的にそうしている)。結果として、ビジネスミッションにも優先順位をつけることになり、重要なはずなのに開発着手されない状態が続くことがありました。一方で、開発チームが取り組むビジネスミッションが切り替わるタイミングでは、チームは連続性を失い、価値を積み上げている実感が薄くなってしまうという課題もありました。

また、プロダクトとしては稼働しており利用者もいるがビジネスミッションからは外れる領域に対して、関心を向けることが許容されにくい状態になっていたことも課題です。限られた開発リソースを取捨選択することは重要ですが、関心ごとの境界としてはハードであり優先順位をつける俎上に載せることすらできないという認識を持つ人が多くなってしまっていました。

これらの課題を解決するため、開発体制の変更を行うことにしました。

体制変更の詳細

今回の体制変更では、チームの分割を行います。チーム分割によってふたつの課題に対処していこうと考えています。
チーム体制は以下のようにしました。

LeSS

この体制に至った経緯

以下、どのような思考プロセスを経てこの体制にしたのかを説明していきます。

1. バリューストリームによるPdMの責務領域の整理

体制を考えるにあたり、DROBEにおけるバリューストリームを可視化する活動が行われました。より正確に表現すると、チーム分割をしたいと考えていた中でPdMの責務領域を整理するタイミングがあり、バリューストリームに沿って責務領域(以下、ビジネスドメイン)を提案しました。

このプロセスによって可視化されたバリューストリームマップは以下の通りです。 本項周辺についてはPO長井による別記事が近日公開予定です。詳細はそちらを参照 & お楽しみに...

VSM

参考:バリューストリーム / バリューストリームマッピングとは

www.atlassian.com

2. Team Topologiesによる将来のチーム体制の明示

可視化されたバリューストリームと担当PdMの情報をもとに、Team Topologiesの考え方でチームの構造を定義しました。

ちいとぽ

参考:チームトポロジーとは

www.ryuzee.com

点線で表現された箱は現時点でまだ実態として存在していない概念です。

  • xOpsはエンジニア採用が進捗し開発キャパシティが増加したタイミングでビジネスオペレーションのプラットフォームとして、中長期的なミッションを持ったチームの組成を検討したいと考えています
    • ミッションは「一連のビジネスオペレーションを包括した、全社のスループット向上」です
  • 倉庫の領域は現時点で両チームに関係していますが専門チームを作るほどの開発キャパシティはないため、当面は両チームで分担して開発・運用を行っていきます
  • MLについては、プラットフォームチーム化した上でプラットフォーム + イネーブリングという振る舞いに変えていこうと考えています

今回の「チーム体制の変更」で対象となるのは以下の2つです。これらは、チームとして自律的に活動できるようになった時点で、2つのストリームアラインドチーム(以下、SAチーム)として独立させることも選択肢として考えています。

  • 商品供給チーム
    • DROBE事業の商品調達から商品価値向上に伴う販売の促進を主務として担うチーム
  • 顧客体験チーム
    • DROBE事業のマーケットからの顧客獲得および購入体験向上伴う販売の促進を主務として担うチーム

3. スクラムの運用を考える

2の後半で示した通りチームとして自律的に活動できるようになった時点で物理的なチーム分割を検討します。スクラム的に言うとふたつのスクラムチームになります。裏を返すと現時点ですぐにふたつのスクラムチームにすることはできないということです。そのため、冒頭で示したLarge Scale Scrum(以下、LeSS)でのチーム分割手法を採用しました。

再掲: チーム体制

LeSS

参考: Large Scale Scrumとは www.atlassian.com

DROBE開発チームでは2週間スプリントでスクラムを運用しています。LeSSにすることで、イベントの流れが以下のようになります。

イベントの流れ

以下が、我々のチーム固有の状況に合わせたカスタマイズになります。

  • 各ビジネスドメインの担当PdMのことを、「代表者」と定義しています。スクラムにはPdMという役割が存在しないため、代表者にマッピングをしました。SAチームとして独立する際には、代表者ではなくPOとなり、スクラムチームから生み出される価値を最大化することに説明責任を持つようになる想定です。
  • チームは担当ビジネスドメインの専門家になることが期待されています。一方で、今回はハードなチーム分割をしない選択肢を取っているため、プロダクト全体を薄く把握した上で担当ビジネスドメインを習熟していくことを期待しています。Sprint Goalによっては他チームのヘルプに行くこともありますし、全体把握を目的に相手チームが担当するビジネスドメインのタスクを受け持つこともあります。
  • Sprint Goalは、事前にPOが素案を提出することで方向性を示します。Backlog Refinement、Sprint Planning1を経て今スプリントで取り組むPBIが明確になるため、Sprint Planning2にてそれらを持ち寄り、各チームがSprint Goalを決定します。Planning2にて方向性を見直したいとなった場合は、POとすり合わせを行いフィックスさせます。
  • 「トラベラー」は、各チームには所属せず各チームでその専門性が必要とされた時に支援に入ります
    • デザイナーは1名しかおらず両チームに所属できないため、デザインの観点でイベントやMTGに参加してほしい時に声をかける運用となります
    • xOps担当PdMはOpsのIssueを都度Planning1に持ち込み、優先順位をつけスプリントに組み込んでいく活動をします。また、必要に応じて各チームに所属しxOps関連タスクのデリバリーを支援します。

体制変更後の状態

最後に、体制変更から1スプリントが経過した現在(2023/08/29)の所感を書いて、本記事を締めたいと思います。 現時点でいくつかポジティブな変化が見えています。

  • チーム内の発言量が増しました
  • 意識するビジネスドメインが狭まったことで、コンテキストが揃っている前提で会話ができるようになりました
  • デプロイ頻度と変更のリードタイムが改善しています
    • ここは他の要因があるかもしれないのですが、タイミング的には一致しているので経過を見守っていきたいと考えています
      デプロイ頻度と変更のリードタイム

一方で、改善したいこともいくつか見えてきています。

  • 1つのゴールに向き合う開発者が減った中で、これまでの進め方だと結果非効率になるケースが散見されています
    • リソース効率で動いていることがあり、フロー効率で見ると改善の余地があります
    • チームの境界が曖昧になっている時が稀にあり、チームのゴール達成やチームを成長させるために頭を使う(新しい価値を作る)ことをもっとやれるはず
  • チームが別れリモートワークも相まって別チームのメンバーとのコミュニケーションが減ってしまった
    • 開発の観点ではポジティブかつ想定される効果ですが、分断はさせたくないためバランスを取る必要があります
    • 夕方に任意で雑談を行う「Coffee Time」を設けてみましたが、効果のほどはまだ不明です
  • 新しい概念をそれなりに取り入れているため、まだ理解が浸透していない(それはそう)
    • ここはSM(含む自分)ががんばっていきます

どんなフレームワークも運用がキモなので、これから数ヶ月よりよい状態に持っていけるように取り組んでいきます!!

PyCon APAC 2023にシルバースポンサーとして協賛します

EMの加川(@shinpr_p)です。
DROBE は PyCon APAC 2023 にシルバースポンサーとして協賛します。

PyCon APACは、プログラミング言語「Python」を中心としたボランティアによる非営利の年次カンファレンスです。このカンファレンスの目的は、Pythonプログラミング言語とその周辺技術を探求し、議論・実践できる場を提供することです。日本での開催は2013年以来の10年ぶりとなります。

DROBEからも数名のメンバーが参加します。ブース出展も行い、ノベルティも現在鋭意製作中です!当日は現地で交流できることを楽しみにしています。

PyCon APAC 2023 の概要

2023-apac.pycon.jp

開催日

2023.10.27(Fri)-28(Sat)

開催地

TOC有明コンベンションホール
東京都江東区有明3丁目5番7号

さいごに

DROBE は「すべての人がポジティブに意思決定し、自分を楽しめる世界」というビジョンを目指し、パーソナルスタイリングサービス「DROBE」を提供しています。

技術コミュニティが創出した成果を活用することで、DROBEというプロダクトを素早くデリバリーすることが可能となっています。技術コミュニティの恩恵をただ享受するだけでなく、業界の発展のために微力ながら貢献していきたいと考え、活動の一環として技術イベントへのスポンサードを行っています。
今後も当社の活用する技術領域にまつわるスポンサードや情報発信を継続的に行っていきます!

当社の紹介

DROBEのプロダクト開発組織に関する情報をまとめておりますので、少しでも興味を持っていただけたらぜひ参照ください。 info.drobe.co.jp


DROBE開発組織の紹介
組織情報ポータル