gpt-4oの動画処理サンプルをDatabricksで動かしてみる

こちらの後半です。

https://qiita.com/taka_yayoi/items/791604d09d1695e6b3c1

```py
%pip install --upgrade openai --quiet
dbutils.library.restartPython()
```

```py
from openai import OpenAI 
import os

## Set the API key and model name
MODEL="gpt-4o"
client = OpenAI(api_key=dbutils.secrets.get(scope="demo-token-takaaki.yayoi", key="openai_api_key"))
```

# 動画処理のセットアップ

動画処理では2つのパッケージを使います - opencv-pythonとmoviepyです。

これらは[ffmpeg](https://ffmpeg.org/about.html)を必要とするので、事前にインストールするようにしてください。お使いのOSによって、`brew install ffmpeg`や`sudo apt install ffmpeg`を実行する必要があるかもしれません。

```py
%pip install opencv-python --quiet
%pip install moviepy --quiet
```

:::note info
**注意**
Databricksランタイムにはffmpegがインストール済みです。
:::

# 動画を二つのコンポーネントに処理: フレームと音声

[こちら](https://github.com/openai/openai-cookbook/blob/main/examples/gpt4o/data/keynote_recap.mp4)の動画をダウンロードして、ワークスペースにインポートしておきます。
![Screenshot 2024-05-16 at 16.22.47.png](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/1168882/d39c8909-2646-ffe3-e3cc-d5dc32128f43.png)

```py
from IPython.display import Image, display, Audio, Markdown
import base64
```

```py
import cv2
from moviepy.editor import VideoFileClip
import time
import base64

# ここでは、OpenAI DevDay Keynote Recapの動画を使います。 こちらから動画を確認できます: https://www.youtube.com/watch?v=h02ti0Bl6zk
VIDEO_PATH = "data/keynote_recap.mp4"
```

```py
def process_video(video_path, seconds_per_frame=2):
    base64Frames = []
    base_video_path, _ = os.path.splitext(video_path)

    video = cv2.VideoCapture(video_path)
    total_frames = int(video.get(cv2.CAP_PROP_FRAME_COUNT))
    fps = video.get(cv2.CAP_PROP_FPS)
    frames_to_skip = int(fps * seconds_per_frame)
    curr_frame=0

    # 動画をループし、指定されたサンプリングレートでフレームを抽出
    while curr_frame < total_frames - 1:
        video.set(cv2.CAP_PROP_POS_FRAMES, curr_frame)
        success, frame = video.read()
        if not success:
            break
        _, buffer = cv2.imencode(".jpg", frame)
        base64Frames.append(base64.b64encode(buffer).decode("utf-8"))
        curr_frame += frames_to_skip
    video.release()

    # 動画から音声を抽出
    audio_path = f"{base_video_path}.mp3"
    clip = VideoFileClip(video_path)
    clip.audio.write_audiofile(audio_path, bitrate="32k")
    clip.audio.close()
    clip.close()

    print(f"Extracted {len(base64Frames)} frames")
    print(f"Extracted audio to {audio_path}")
    return base64Frames, audio_path

# 秒あたり1フレームを抽出。サンプリングレートを変更するために `seconds_per_frame` パラメーターを使うことができます
base64Frames, audio_path = process_video(VIDEO_PATH, seconds_per_frame=1)
```

```py
## コンテキストのフレームと音声を表示
display_handle = display(None, display_id=True)
for img in base64Frames:
    display_handle.update(Image(data=base64.b64decode(img.encode("utf-8")), width=600))
    time.sleep(0.025)

Audio(audio_path)
```
![Screenshot 2024-05-16 at 16.23.40.png](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/1168882/f3d022d4-dd5f-ec08-878f-6b815c35aa9b.png)

# サンプル 1: 要約

動画フレームと音声の準備ができたので、様々なモダリティを持つモデルを用いた結果を比較するための動画の要約を生成するために、いくつかのテストを実行してみましょう。モデルは動画からの全体のコンテキストを活用できるので、画像と音声の入力の両方のコンテキストで生成されたサマリーがもっとも正確であることを確認できるはずです。

1. 視覚的な要約
2. 音声の要約
3. 視覚的 + 音声の要約

## 画像の要約

画像の要約は動画のフレームのみをモデルに送信することで生成されます。フレームだけを用いて、モデルは視覚的な側面をキャプチャしますが、スピーカーによって議論されている詳細を捉えることはできません。

```py
response = client.chat.completions.create(
    model=MODEL,
    messages=[
    {"role": "system", "content": "動画の要約を生成してください。マークダウンでレスポンスをしてください。"},
    {"role": "user", "content": [
        "こちらが動画のフレームです。",
        *map(lambda x: {"type": "image_url", 
                        "image_url": {"url": f'data:image/jpg;base64,{x}', "detail": "low"}}, base64Frames)
        ],
    }
    ],
    temperature=0,
)
print(response.choices[0].message.content)
```

```
## 動画の要約

### OpenAI DevDay キーノート

1. **オープニング**:
   - 「OPENAI DEVDAY」のタイトルが表示され、イベントの開始を告げる。

2. **会場の様子**:
   - 会場の外観や内部の様子が映し出され、多くの参加者が集まっている。

3. **キーノートスピーカーの登場**:
   - スピーカーが登壇し、イベントの概要と目的について説明。

4. **GPT-4 Turboの発表**:
   - GPT-4 Turboの紹介。新機能や性能向上について説明。
   - JSONモードや関数呼び出し機能のデモンストレーション。

5. **新機能の紹介**:
   - コンテキスト長の拡大、制御の向上、知識の向上など、GPT-4 Turboの新機能について詳細に説明。

6. **DALLE-3の発表**:
   - DALLE-3の紹介。画像生成能力の向上について説明。

7. **カスタムモデルの紹介**:
   - ユーザーが独自のモデルを作成・カスタマイズできる機能の紹介。

8. **APIの紹介**:
   - 新しいAPI機能について説明。スレッディング、リトリーバル、コードインタープリター、関数呼び出しなどの機能を紹介。

9. **GPTsの紹介**:
   - GPTsの新しいアプリケーションやユースケースについて説明。

10. **クロージング**:
    - スピーカーがイベントを締めくくり、参加者に感謝の意を表明。

### まとめ
OpenAI DevDayでは、GPT-4 TurboやDALLE-3などの新技術が発表され、参加者に向けて詳細なデモンストレーションが行われました。新機能やAPIの紹介を通じて、開発者がどのようにこれらの技術を活用できるかが示されました。
```
![Screenshot 2024-05-16 at 16.25.06.png](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/1168882/1a9c1758-b29e-3a58-4d60-8d36e9b3a658.png)

結果は期待通りです - モデルは動画の画像のハイレベルな側面を細くすることはできていますが、スピーチで提供される詳細は見逃しています。

## 音声のサマリー

音声のサマリーはモデルに音声録音を送信することで生成されます。音声だけの場合、音声のコンテンツのバイアスが生じる場合があり、プレゼンテーションや画像から提供されるコンテキストを見逃してしまいます。

GPT-4oの`{audio}`入力は現時点では利用できず、間も無く利用できるようになります！現時点では、音声を処理するために既存の`whisper-1`モデルを使います。

```py
# 音声の書き起こし
transcription = client.audio.transcriptions.create(
    model="whisper-1",
    file=open(audio_path, "rb"),
)
## オプション: 書き起こしを表示するには以下の行のコメントを解除してください
#print("Transcript: ", transcription.text + "\n\n")

response = client.chat.completions.create(
    model=MODEL,
    messages=[
    {"role": "system", "content":"""書き起こしのサマリーを日本語で作成してください。マークダウンでレスポンスしてください。"""},
    {"role": "user", "content": [
        {"type": "text", "text": f"書き起こしはこちら: {transcription.text}"}
        ],
    }
    ],
    temperature=0,
)
print(response.choices[0].message.content)
```

```
## サマリー

OpenAIの初のDev Dayで、以下の新機能とプログラムが発表されました。

1. **GPT-4 Turbo**:
   - 最大128,000トークンのコンテキストをサポート。
   - JSONモードで有効なJSONを返す機能。
   - 複数の関数を同時に呼び出すことが可能。
   - 世界の知識を2023年4月まで持ち、今後も改善予定。

2. **新機能とAPI**:
   - 外部ドキュメントやデータベースから知識を取得するリトリーバル機能。
   - Dolly 3、GPT-4 Turbo with Vision、新しいText-to-SpeechモデルがAPIに追加。
   - カスタムモデルプログラムの開始。
   - GPT-4のトークン制限を倍増し、レートリミットとクォータの変更をAPIアカウント設定でリクエスト可能。
   - GPT-4 TurboはGPT-4よりもプロンプトトークンで3倍、コンプリートトークンで2倍安価。

3. **GPTs**:
   - 特定の目的に合わせたChatGPTのカスタムバージョン。
   - コーディング不要で会話を通じてプログラム可能。
   - プライベートGPTの作成やリンクを通じた共有が可能。
   - ChatGPT Enterpriseでは会社専用のGPTを作成可能。
   - GPTストアの今月中のローンチ予定。

4. **Assistance API**:
   - 永続的なスレッド、ビルトインリトリーバル、コードインタープリタ、サンドボックス環境でのPythonインタープリタ、改良された関数呼び出しを含む。

これらの技術により、ユーザーはより多くのことを簡単に実行できるようになり、未来の構築に貢献することが期待されています。
```
![Screenshot 2024-05-16 at 16.26.27.png](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/1168882/4d31ad8f-0105-d35a-5acc-5c6e8ebb5cde.png)

音声のサマリーはスピーチで議論されたコンテンツのバイアスを受けますが、画像のサマリーよりもシンプルな構造となっています。

## 音声 + 視覚的な要約

音声 + 視覚的な要約は、動画の画像と音声の両方を一度にモデルに送信することで生成されます。これらの両方を送信する際、モデルは一度に動画全体を理解できるので、より優れた要約が期待できます。

```py
## 画像と音声の要約の生成
response = client.chat.completions.create(
    model=MODEL,
    messages=[
    {"role": "system", "content":"""動画のサマリーを作成してください。指定される動画と書き起こしから要約を日本語で作成してください。マークダウンでレスポンスしてください。"""},
    {"role": "user", "content": [
        "これらが動画のフレームです。",
        *map(lambda x: {"type": "image_url", 
                        "image_url": {"url": f'data:image/jpg;base64,{x}', "detail": "low"}}, base64Frames),
        {"type": "text", "text": f"音声の書き起こしはこちらです: {transcription.text}"}
        ],
    }
],
    temperature=0,
)
print(response.choices[0].message.content)
```
```
## 動画のサマリー

OpenAIの初のDev Dayでは、いくつかの新しい発表が行われました。以下はその主な内容です。

1. **GPT-4 Turboの発表**:
   - 新しいモデルであるGPT-4 Turboが発表されました。このモデルは最大128,000トークンのコンテキストをサポートします。
   - JSONモードという新機能が追加され、モデルが有効なJSONで応答することを保証します。
   - 複数の関数を同時に呼び出すことができ、指示に従う能力が向上しました。

2. **知識の向上**:
   - プラットフォームにリトリーバル機能が追加され、外部のドキュメントやデータベースから知識を取り込むことが可能になりました。
   - GPT-4 Turboは2023年4月までの世界の知識を持ち、今後も改善が続けられます。

3. **新しいAPI機能**:
   - Dolly 3、GPT-4 Turbo with Vision、新しいテキスト読み上げモデルがAPIに追加されました。
   - カスタムモデルプログラムが開始され、企業が特定のユースケースに合わせたカスタムモデルを作成するために研究者と協力できます。

4. **トークン制限の緩和**:
   - GPT-4の既存の顧客向けに、1分あたりのトークン数が2倍に増加しました。
   - APIアカウント設定でレートリミットやクォータの変更を直接リクエストできるようになりました。

5. **コスト削減**:
   - GPT-4 Turboは、プロンプトトークンで3倍、コンプリートトークンで2倍のコスト削減が実現されました。

6. **GPTsの導入**:
   - GPTsは特定の目的に合わせたChatGPTのカスタムバージョンで、指示、拡張知識、アクションを組み合わせてより役立つものとなります。
   - コーディングの知識がなくても、会話を通じてGPTをプログラムすることが可能です。
   - プライベートGPTの作成や、リンクを通じた公開、ChatGPT Enterpriseを利用した企業専用のGPTの作成が可能です。
   - GPTストアが今月中にローンチされる予定です。

7. **APIの拡張**:
   - Assistance APIには、長い会話履歴を処理するための持続的なスレッド、組み込みのリトリーバル、Pythonインタープリタを含むコードインタープリタ、改良された関数呼び出しが含まれます。

最後に、OpenAIはこの技術を使って新しい未来を共に築くことを楽しみにしていると述べ、来年のDev Dayへの期待を表明しました。
```
![Screenshot 2024-05-16 at 16.27.20.png](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/1168882/62886224-47d1-920a-441f-d7af1ab17763.png)

動画と音声を組み合わせることで、動画から得られる画像と音声の両方の要素の情報を用いたはるかに詳細かつ包括的な要約を取得することができます。

# サンプル 2: 質疑応答

Q&Aにおいては、入力のモダリティを組み合わせるメリットを示すために、同じ3つのテストを実行する過程で処理した動画に対する質問を行う際に、上と同じコンセプトを活用します:
1. 視覚的なQ&A
2. 音声に関するQ&A
3. 視覚的 + 音声のQ&A 

```py
QUESTION = "質問: なぜSam Altmanは窓を開けてラジオをオンにするという例を用いたのですか？"
```

```pt
qa_visual_response = client.chat.completions.create(
    model=MODEL,
    messages=[
    {"role": "system", "content": "指定された質問に対して回答するために動画を使ってください。マークダウンでレスポンスしてください。"},
    {"role": "user", "content": [
        "こちらが動画のフレームです。",
        *map(lambda x: {"type": "image_url", "image_url": {"url": f'data:image/jpg;base64,{x}', "detail": "low"}}, base64Frames),
        QUESTION
        ],
    }
    ],
    temperature=0,
)
print("Visual QA:\n" + qa_visual_response.choices[0].message.content)
```

> Visual QA:
> Sam Altmanは、窓を開けてラジオをオンにするという例を用いて、GPT-4 Turboの新しい機能である「Function calling」を説明しました。この機能は、ユーザーの指示をより正確に理解し、実行するためのものです。具体的には、以前はユーザーが「窓を開けてラジオをオンにして」と言った場合、システムはそれぞれの指示を個別に処理していましたが、新しい機能ではこれを一つの統合された指示として処理し、より効率的に実行できるようになっています。この例を用いることで、Function callingの利便性と精度の向上を具体的に示しています。

```py
qa_audio_response = client.chat.completions.create(
    model=MODEL,
    messages=[
    {"role": "system", "content":"""指定された質問に回答するために書き起こしを使ってください。マークダウンでレスポンスしてください。"""},
    {"role": "user", "content": f"音声の書き起こしはこちらです: {transcription.text}. \n\n {QUESTION}"},
    ],
    temperature=0,
)
print("Audio QA:\n" + qa_audio_response.choices[0].message.content)
```

> Audio QA:
> 書き起こしの内容には、Sam Altmanが「窓を開けてラジオをオンにする」という例を用いたという記述は含まれていません。そのため、この質問に対する具体的な回答は提供できません。
>
> もし他に質問があれば、お知らせください。

```py
qa_both_response = client.chat.completions.create(
    model=MODEL,
    messages=[
    {"role": "system", "content":"""指定された質問に回答するために動画と書き起こしを使ってください。"""},
    {"role": "user", "content": [
        "こちらが動画のフレームです",
        *map(lambda x: {"type": "image_url", 
                        "image_url": {"url": f'data:image/jpg;base64,{x}', "detail": "low"}}, base64Frames),
                        {"type": "text", "text": f"音声の書き起こしはこちらです: {transcription.text}"},
        QUESTION
        ],
    }
    ],
    temperature=0,
)
print("Both QA:\n" + qa_both_response.choices[0].message.content)
```

> Both QA:
> Sam Altmanは「窓を開けてラジオをオンにする」という例を用いて、GPT-4 Turboの新機能である「関数呼び出し」機能を説明しました。この機能により、モデルが複数の関数を同時に呼び出すことができ、指示に従う能力が向上することを示しています。この例は、複数のアクションを一度に実行する能力を具体的に示すために使われました。

3つの回答を比較すると、最も正確な回答は、動画の画像と音声の両方を用いたものとなっています。Sam Altomanはキーノートで窓を開けることやラジオに関して議論していませんが、彼の背後で表示されている例として、単一リクエストで複数の関数を実行できるモデルの能力を参照しています。

# まとめ

音声、画像、テキストのような複数の入力モダリティを連携することで、様々なタスクにおけるモデルのパフォーマンスを劇的に強化できます。このマルチモーダルアプローチによって、人間がどのように情報を認識し、処理するのかに対して、より包括的な理解やインタラクション、模倣することが可能となります。

現時点では、APIでのGPT-4oはテキストと画像入力のみであり、音声の機能は間も無く提供されます。

### はじめてのDatabricks

[はじめてのDatabricks](https://qiita.com/taka_yayoi/items/8dc72d083edb879a5e5d)

### Databricks無料トライアル

[Databricks無料トライアル](https://databricks.com/jp/try-databricks)