health-reader / app.py
matsuap's picture
Update app.py
a5380ab verified
import gradio as gr
import openai
import base64
import pandas as pd
import uuid
import io
import os
def analyze_image(image_path, api_key):
"""
画像を読み込み、base64エンコードした上で
指定したOpenAI API (gpt-4o-mini) に投げてCSVを取得し、
テーブル表示用データとダウンロード用ファイルを返す
"""
# 画像またはAPIキーが未入力の場合はメッセージを返す
if not image_path:
return "画像をアップロードしてください。", None
if not api_key:
return "API Key を入力してください。", None
# 画像をbase64に変換
with open(image_path, "rb") as f:
image_data = f.read()
image_base64 = base64.b64encode(image_data).decode("utf-8")
# UUIDはOpenAI側に生成を指示してもよいですが、こちらで生成してもOKです。
# ここではOpenAIに完全に任せるため、プロンプトで生成を依頼する例とします。
# 必要に応じてこちらで生成した UUID を挿入することも可能です。
# ChatGPT(gpt-4o-mini)に送るユーザープロンプト
user_prompt = f"""
以下の画像に写っている各部位の計測値(首、肩、二の腕L、二の腕R、胸、ウエスト、ヒップ、太腿L、太腿R、ふくらはぎL、ふくらはぎR)を読み取り、
次のCSVフォーマットで出力してください。なお、CSVの1行目には列名を、2行目には画像から抽出した数値を入れてください。
左端のID列には自動生成したUUIDを記載してください。
出力には余計な説明文を加えず、CSVテキストのみとせよ。
- CSVフォーマット例:
ID,首,肩,二の腕L,二の腕R,胸,ウエスト,ヒップ,太腿L,太腿R,ふくらはぎL,ふくらはぎR
<自動生成UUID>,<首の数値>,<肩の数値>,<二の腕L>,<二の腕R>,<胸>,<ウエスト>,<ヒップ>,<太腿L>,<太腿R>,<ふくらはぎL>,<ふくらはぎR>
もし画像から読み取れない数値があれば空欄や"N/A"としてください。
"""
try:
# OpenAI API呼び出し
client = openai.OpenAI(api_key=api_key)
response = client.chat.completions.create(
model="gpt-4o-mini",
messages=[
{
"role": "user",
"content": [
{
"type": "text",
"text": user_prompt,
},
{
"type": "image_url",
"image_url": {
"url": f"data:image/png;base64,{image_base64}",
}
},
]
}
],
temperature=0.0
)
except Exception as e:
return f"API呼び出しエラー: {str(e)}", None
# APIの応答(CSVテキスト想定)
csv_text = response.choices[0].message.content.strip()
csv_text = csv_text.replace('```', '')
# pandasでテーブルに変換を試みる
try:
df = pd.read_csv(io.StringIO(csv_text))
except Exception as e:
# CSVとしてパースできなければテキストのみ返す
return f"CSVとして解析できませんでした。応答内容:\n{csv_text}", None
# CSVをtemp.csvに出力する
df.to_csv('temp.csv', index=False)
return df, 'temp.csv'
# Gradioアプリの定義
with gr.Blocks() as demo:
gr.Markdown("# 画像から数値を読み取り、CSVを生成するデモアプリ")
api_key_input = gr.Textbox(
label="OpenAI API Key",
placeholder="sk-...",
type="password",
show_label=True
)
image_input = gr.Image(
label="画像アップロード",
type="filepath"
)
generate_button = gr.Button("CSV生成", variant="primary")
download_button = gr.DownloadButton("CSVダウンロード")
# 出力は DataFrame と File (ダウンロード用)
output_table = gr.DataFrame(label="CSVプレビュー")
# ボタンクリック時の動作
generate_button.click(
fn=analyze_image,
inputs=[image_input, api_key_input],
outputs=[output_table, download_button]
)
if __name__ == "__main__":
demo.launch()