Gemini-1.5-flash
Gemini 1.5の新バージョンであるgemini-1.5-flashの性能を試してみたいと思います!
gemini1.5-flashはコンテキストウィンドウが1Mを誇り、動画や音声を適当に投げても、相当な精度で内容を理解してくれます。
今回のアップデートでどれほどの能力を身につけたのか、早速試してみます。
音声データの認識
gemini-1.5-flashでは、音声データをそのままプロンプトにくっつけて投げることができます。
ただし、鵜呑みにしてファイルをプロンプトにくっつけて投げると、8MBまでの容量制限を受けることになります。
そのため、GCPのCloud Strageにファイルをアップロードして、そのURIをモデルの入力とします。
さくっとStreamlitでアプリを作ってみました。
import streamlit as st
from google.cloud import storage
from google.generativeai import GenerativeModel
import base64
import vertexai
from vertexai.generative_models import GenerativeModel, Part, FinishReason
import vertexai.preview.generative_models as generative_models
import time
# GCPの設定 (Cloud Storage, Gemini API)
BUCKET_NAME = 'CloudStrageのバケット名'
SERVICE_ACCOUNT_KEY_FILE = 'サービスアカウントのキーファイルへのパス'
PROJECT_NAME = 'プロジェクト名'
REGION_NAME = 'リージョン'
storage_client = storage.Client.from_service_account_json(SERVICE_ACCOUNT_KEY_FILE)
bucket = storage_client.bucket(BUCKET_NAME)
def generate(audio_file):
vertexai.init(project=PROJECT_NAME, location=REGION_NAME)
model = GenerativeModel(
"gemini-1.5-flash-preview-0514",
)
responses = model.generate_content(
[audio_file, """この音声は、ある会議の音声です。この音声をもとに会議の要約を作成してください。
音声に含まれていない情報をでっち上げたり、冗長になったりしてはいけません。
まず、会議の概要、何が議論されたのか、会議の結論、アクションアイテムを冒頭にまとめて記載してください。
会議の概要には、会議名、日時、参加者が必要です。開催日時などが不明の場合は「不明」と記載してください。
また内容はMECEである必要があります。
その後、会議の流れを記載します。
会議の流れは下記の形式で、それぞれのタイムスタンプごとの話題の概要を記載します。
もしも補足するべき内容があれば、備考に記載してください。表の中はすべて左詰となるようにします。
|タイムスタンプ|話題|備考|
"""],
generation_config=generation_config,
safety_settings=safety_settings,
stream=True,
)
return responses
def delete_all_blobs(bucket_name):
bucket = storage_client.bucket(bucket_name)
blobs = list(bucket.list_blobs())
for blob in blobs:
blob.delete()
st.toast("全てのBlobを削除しました", icon='😃')
safety_settings = {
generative_models.HarmCategory.HARM_CATEGORY_HATE_SPEECH: generative_models.HarmBlockThreshold.BLOCK_MEDIUM_AND_ABOVE,
generative_models.HarmCategory.HARM_CATEGORY_DANGEROUS_CONTENT: generative_models.HarmBlockThreshold.BLOCK_MEDIUM_AND_ABOVE,
generative_models.HarmCategory.HARM_CATEGORY_SEXUALLY_EXPLICIT: generative_models.HarmBlockThreshold.BLOCK_MEDIUM_AND_ABOVE,
generative_models.HarmCategory.HARM_CATEGORY_HARASSMENT: generative_models.HarmBlockThreshold.BLOCK_MEDIUM_AND_ABOVE,
}
st.set_page_config(
page_title="Gemini-1.5-pro / マルチモーダル",
page_icon="🚀",
layout="wide",
initial_sidebar_state="expanded",
)
with st.sidebar:
st.subheader('Generation config')
max_output_tokens = st.slider(label="出力トークンサイズ", min_value=1024, max_value=8192, value=8192)
temperature = st.slider(label="Temperature", min_value=0.0, max_value=1.0, value=1.0)
top_p = st.slider(label="Top P", min_value=0.0, max_value=1.0, value=0.95)
st.subheader('Cloud Storage')
st.button(label="Cloud Strage内のファイルを全て消去", on_click=delete_all_blobs, args=(BUCKET_NAME,))
generation_config = {
"max_output_tokens": max_output_tokens,
"temperature": temperature,
"top_p": top_p,
}
st.title('音声ファイルから議事録を作る')
uploaded_file = st.file_uploader("音声ファイルを選択します", type=["mp3", "wav"])
if uploaded_file is not None:
with st.status("議事録を作成しています...", expanded=True) as status:
# ステータス表示
status_text = st.empty() # ステータスメッセージを表示する場所を確保
# Cloud Storageにアップロード
blob = bucket.blob(uploaded_file.name)
status.write("音声ファイルをアップロードしています...") # アップロード中であることを表示
blob.upload_from_file(uploaded_file)
status.write("議事録を作成しています...") # アップロード中であることを表示
# Gemini APIで議事録作成
gcs_uri = f'gs://{BUCKET_NAME}/{uploaded_file.name}'
audio1 = Part.from_uri(
mime_type="audio/wav",
uri=gcs_uri)
response = generate(audio1)
status.update(label="完了しました", expanded=False, state="complete")
# 議事録をリアルタイム表示
minutes_container = st.empty()
minutes = ""
for chunk in response: # type: ignore
minutes += chunk.text
minutes_container.write(minutes)
time.sleep(0.05)
動かしてみる
サクッと機能を試したいだけなので、いろいろ汚いコードになってしまいました…
Streamlitで簡単に動かしてみます。
streamlit run Gemini_Gijiroku.py
画面が立ち上がりましたので、早速音声ファイルを入力してみます。
今回は下記のnoteで公開されていた、新入社員向けの議事録練習用の会議音声を利用します(そんなのあるんですね…)
結果
会議の内容を正確に捉えています。
会議の流れもまとめるように指示していたので、その結果も見てみましょう。
完璧ですね。後から会議の模様をキャッチアップすることも簡単です。
ただ音声ファイルをそのまま投げただけでこの精度とは、恐れ入ります。
動画データの認識
同様の手順で動画データもそのままモデルへの入力とすることができます。
Gemini-1.5では、動画中の音声データもそのまま理解してくれるとのことなので、面倒な事前処理は不要です。
先ほどのコードを少し編集し、これも試してみます。
import streamlit as st
from google.cloud import storage
from google.generativeai import GenerativeModel
import base64
import vertexai
from vertexai.generative_models import GenerativeModel, Part, FinishReason
import vertexai.preview.generative_models as generative_models
import time
# GCPの設定 (Cloud Storage, Gemini API)
BUCKET_NAME = 'CloudStrageのバケット名'
SERVICE_ACCOUNT_KEY_FILE = 'サービスアカウントのキーファイルへのパス'
PROJECT_NAME = 'プロジェクト名'
REGION_NAME = 'リージョン'
storage_client = storage.Client.from_service_account_json(SERVICE_ACCOUNT_KEY_FILE)
bucket = storage_client.bucket(BUCKET_NAME)
def generate(audio_file):
vertexai.init(project=PROJECT_NAME, location=REGION_NAME)
model = GenerativeModel(
"gemini-1.5-flash-preview-0514",
)
contents = [video_file, """この動画は、何かのコンテキストを持っています。この動画をもとに要約を作成してください。
動画に含まれていない情報をでっち上げたり、冗長になったりしてはいけません。
まず、動画の概要、被写体は何か、コンテキストは何かを記載します。
コンテキストが不明な場合は、推測して記載してください。その際は「(推測)」と末尾につけてください。
フォーマットは下記の通りとします:
## 動画の概要
<動画の概要を記載>
### コンテキスト
<コンテキストを記載>
その後、動画の流れを記載します。
動画の流れは下記の形式で、それぞれのタイムスタンプごとの概要を記載します。
もしも補足するべき内容があれば、備考に記載してください。表の中はすべて左詰となるようにします。
### 動画の流れ
|タイムスタンプ|コンテキスト|備考|
"""]
tokens = model.count_tokens(contents)
responses = model.generate_content(
contents,
generation_config=generation_config,
safety_settings=safety_settings,
stream=True,
)
return [responses, tokens]
def delete_all_blobs(bucket_name):
bucket = storage_client.bucket(bucket_name)
blobs = list(bucket.list_blobs())
for blob in blobs:
blob.delete()
st.toast("全てのBlobを削除しました", icon='😃')
safety_settings = {
generative_models.HarmCategory.HARM_CATEGORY_HATE_SPEECH: generative_models.HarmBlockThreshold.BLOCK_MEDIUM_AND_ABOVE,
generative_models.HarmCategory.HARM_CATEGORY_DANGEROUS_CONTENT: generative_models.HarmBlockThreshold.BLOCK_MEDIUM_AND_ABOVE,
generative_models.HarmCategory.HARM_CATEGORY_SEXUALLY_EXPLICIT: generative_models.HarmBlockThreshold.BLOCK_MEDIUM_AND_ABOVE,
generative_models.HarmCategory.HARM_CATEGORY_HARASSMENT: generative_models.HarmBlockThreshold.BLOCK_MEDIUM_AND_ABOVE,
}
st.set_page_config(
page_title="Gemini-1.5-pro / マルチモーダル",
page_icon="🚀",
layout="wide",
initial_sidebar_state="expanded",
)
with st.sidebar:
st.subheader('Generation config')
max_output_tokens = st.slider(label="出力トークンサイズ", min_value=1024, max_value=8192, value=8192)
temperature = st.slider(label="Temperature", min_value=0.0, max_value=1.0, value=1.0)
top_p = st.slider(label="Top P", min_value=0.0, max_value=1.0, value=0.95)
st.subheader('Cloud Storage')
st.button(label="Cloud Strage内のファイルを全て消去", on_click=delete_all_blobs, args=(BUCKET_NAME,))
generation_config = {
"max_output_tokens": max_output_tokens,
"temperature": temperature,
"top_p": top_p,
}
st.title('動画ファイルを読み込んで内容を解釈する')
uploaded_file = st.file_uploader("動画ファイルを選択します", type=["mp4"])
if uploaded_file is not None:
with st.status("動画を分析しています...", expanded=True) as status:
# ステータス表示
status_text = st.empty() # ステータスメッセージを表示する場所を確保
# Cloud Storageにアップロード
blob = bucket.blob(uploaded_file.name)
status.write("動画ファイルをアップロードしています...") # アップロード中であることを表示
blob.upload_from_file(uploaded_file)
status.write("回答を準備しています...") # アップロード中であることを表示
# Gemini APIで議事録作成
gcs_uri = f'gs://{BUCKET_NAME}/{uploaded_file.name}'
video = Part.from_uri(
mime_type="video/mp4",
uri=gcs_uri)
response_datas = generate(video)
response = response_datas[0]
tokens = response_datas[1]
status.update(label=f"完了しました。トークン数:{tokens.total_tokens}", expanded=False, state="complete")
# 議事録をリアルタイム表示
minutes_container = st.empty()
minutes = ""
for chunk in response: # type: ignore
minutes += chunk.text
minutes_container.write(minutes)
time.sleep(0.05)
ほとんど何も変わっていませんね。
動画データの解釈のために、プロンプトだけ変更しています。
これもStreamlitで起動してみます。
streamlit run Gemini_Douga.py
結果
今回は総務省が公開している、BS・CSの4K・8K放送についての紹介動画を読み込ませてみました。
こういう動画は見る気は起きませんが、みなくても内容がわかれば嬉しいですよね。
今回使ったのは1.4K・8Kの魅力
という動画ファイルで、およそ4分の長さがあります。
早速結果を見てみましょう。
動画の概要やコンテキストをしっかりと認識してくれています。
また音声データと同様に、動画の中身をタイムスタンプ付きで説明してもらいましたが、こちらも非常に正確でした。
まとめ
Gemini-1.5のマルチモーダル性能は強力でした。
特にファイルをそのままモデルに投げるだけで、中身を理解して返答してくれますので、これは活用の幅が広がりそうです。
コンテキストウィンドウも今後2Mへ拡大されるとのことで、よりマルチモーダルの能力を生かした使い方ができそうですね。
おまけ(GPT4o)
ちがうちがうそうじゃない
ちょっと横着してGUIから投げたからかもしれません