Azure OpenAI Assistants APIを使って可視化する
やること
・Assistants APIの基本的な使い方をおさえる
・CSVファイルを与えてデータの可視化を試みる
参考記事
データセット
CSVのサンプルとして以下サイト内の成績一覧表を用いました。
https://www.icon-co.jp/csvlapot/dl/help/samplecsv/1_seiseki.zip
前提
・AOAIにgpt-4o-mini(2024-02-15-preview)をデプロイ済み
・所定のディレクトリにCSVファイルを格納しておく
依存ライブラリ
pip install openai==1.20.0
※何も考えないで最新のバージョンでやるとエラーが起きます。
基本的な流れ
それでは実際にAssistants APIを利用する流れを見ていきます。
STEP1:AOAIクライアントの作成
client = AzureOpenAI(
api_key=os.getenv("AZURE_OPENAI_API_KEY"),
api_version=os.getenv("AZURE_OPENAI_API_VERSION"),
azure_endpoint=os.getenv("AZURE_OPENAI_ENDPOINT")
)
STEP2:Assistantの作成
def create_data_analyst_assistant(
client,
csv_file_id,
assistant_name="Data Analyst Assistant",
model_name="dev-gpt-4o-mini"):
assistant_1 = client.beta.assistants.create(
name=assistant_name,
instructions=f'''
あなたは優秀なデータアナリストです。
ある学級の試験成績のCSVファイルを使って、データを分析してください。
また、分析結果を可視化してください。
''',
tools=[{"type": "code_interpreter"}],
model=model_name,
file_ids = [csv_file_id]
)
for k, v in dict(assistant_1).items():
print(f"{k}: {v}")
return assistant_1
STEP3:Threadの作成・実行
def create_and_run_thread(client, csv_file_name, assistant_1):
# Threadの作成
thread_1 = client.beta.threads.create()
# Messageの追加
message_1 = client.beta.threads.messages.create(
thread_id=thread_1.id,
role="user",
content=f'''
{csv_file_name}の分析結果を可視化してください。
棒グラフやヒストグラムのタイトルやバーの表示は英語で問題ありません。
可視化結果はファイルに保存してください。
'''
)
# Threadの実行
run1_1 = client.beta.threads.runs.create(
thread_id=thread_1.id,
assistant_id=assistant_1.id
)
return thread_1, message_1, run1_1
STEP4:AOAIからの結果待ち
def wait_for_assistant_response(client, thread_id, run_id):
while True:
time.sleep(5)
run = client.beta.threads.runs.retrieve(
thread_id=thread_id,
run_id=run_id
)
status = run.status
if status in ["completed", "cancelled", "expired", "failed"]:
print(status)
break
STEP5:結果の出力
def retrieve_and_print_messages(client, thread_id, verbose, out_dir=None):
# メッセージリストをクライアントから取得
messages = client.beta.threads.messages.list(thread_id=thread_id)
# ユーザーとアシスタントの役割を表示する辞書
display_role = {"user": "User query", "assistant": "Assistant response"}
prev_role = None # 前回のメッセージの役割を保存する変数
# verboseモードが有効な場合、会話の開始を表示
if verbose:
print("\n\nCONVERSATION:")
# メッセージを逆順で処理
for message_data in reversed(messages.data):
# 前回のメッセージがアシスタントで現在がユーザーなら区切りを表示
if prev_role == "assistant" and message_data.role == "user" and verbose:
print("------ \n")
# 各メッセージの内容を処理
for message_content in message_data.content:
txt_val = None
# メッセージがテキストの場合、テキストを取得
if message_content.type == "text":
txt_val = message_content.text.value
# メッセージが画像ファイルの場合、画像データを保存する
elif message_content.type == "image_file" and out_dir is not None:
image_data = client.files.content(message_content.image_file.file_id)
out_dir_path = Path(out_dir)
if out_dir_path.exists():
image_path = out_dir_path / f"{message_content.image_file.file_id}.png"
with image_path.open("wb") as f:
f.write(image_data.read())
# テキストが存在する場合、メッセージの役割と内容を表示
if txt_val is not None and verbose:
print(f"{display_role.get(message_data.role, 'Unknown')}:\n{txt_val}")
prev_role = message_data.role
return messages
実行コード
if __name__ == "__main__":
csv_file = client.files.create(
file=open("<your csv file>", "rb"),
purpose='assistants'
)
csv_file_id = csv_file.id
csv_filename = csv_file.filename
out_dir = "<your directory>"
# Assistantの作成
assistant_1 = create_data_analyst_assistant(client, csv_file_id)
# Threadの作成と実行
thread_1, message_1, run1_1 = create_and_run_thread(client,csv_filename, assistant_1)
# AOAIからの結果待ち
wait_for_assistant_response(client, thread_1.id, run1_1.id)
# 結果の出力
retrieve_and_print_messages(client, thread_1.id, True, out_dir)
結果の可視化
コメントなど
なんとか可視化まではこぎつけましたが、グラフのバーが一部文字化けしてしまっています。これは色々調べてメッセージに追加するプロンプトで「英語でいいよ」と言葉を添えたり、japanaese-matplotlibをクライアントに渡すとかを試しても、結局データセットのカラム名が日本語の場合きちんと表示させるのは難しいようです(上手く表示させる方法知っている人いたら教えてください・・・)
また、AOAIのAssistants APIは9月4日時点でプレビュー版であるため、今後仕様変更に伴い上記の書き方も変わるかもしれません。(https://learn.microsoft.com/ja-jp/azure/ai-services/openai/concepts/assistants )ただでさえ挙動が不安定(何回かに1回はちゃんと出力しない)であることに加えて、openaiやSDKのバージョンによってAssistantやThreadに与える引数も変わるようなので、要注意です。ただ、それを差し置いてもCSVデータを渡すだけでデータ分析の一端を担ってくれる便利なツールだなと感じたので、今後の進展に期待したいところです。
Discussion