medicine / app.py
soiz1's picture
Update app.py
16f8120 verified
raw
history blame
6.55 kB
from PIL import Image
import gradio as gr
from g4f.client import Client
import markdown2
import base64
from io import BytesIO
import io
client = Client()
def truncate_history(history, max_tokens=2048):
truncated_history = []
total_tokens = 0
for user_msg, assistant_msg in reversed(history):
user_tokens = len(user_msg.split())
assistant_tokens = len(assistant_msg.split())
if total_tokens + user_tokens + assistant_tokens > max_tokens:
break
total_tokens += user_tokens + assistant_tokens
truncated_history.insert(0, (user_msg, assistant_msg))
return truncated_history
def format_output(text):
"""
チャットGPTスタイルのマークダウン形式に対応するためのフォーマット関数
"""
return markdown2.markdown(text, extras=[
"fenced-code-blocks",
"tables",
"task_list",
"strike",
"spoiler",
"markdown-in-html"
])
def convert_image_to_dataurl(image):
"""
アップロードされた画像をdataURL形式に変換
"""
buffered = BytesIO()
image.save(buffered, format="PNG")
img_str = base64.b64encode(buffered.getvalue()).decode("utf-8")
return f"data:image/png;base64,{img_str}"
def respond(message, history, system_message, max_tokens, temperature, top_p, model_choice, web_search, image=None):
# 履歴が長すぎないようにトークン数を制限
history = truncate_history(history, max_tokens=2048)
# システムメッセージを先頭に追加
messages = [{"role": "system", "content": system_message}]
# これまでの会話履歴を追加
for user_msg, assistant_msg in history:
if user_msg:
messages.append({"role": "user", "content": user_msg})
if assistant_msg:
messages.append({"role": "assistant", "content": assistant_msg})
# 今回のユーザーメッセージを追加
if image:
# 画像をリサイズしてデータ量を削減
img = Image.open(io.BytesIO(base64.b64decode(image.split(",")[1])))
img = img.resize((512, 512)) # サイズ縮小
buffered = io.BytesIO()
img.save(buffered, format="PNG")
img_data = base64.b64encode(buffered.getvalue()).decode("utf-8")
# 画像データを適切に埋め込む
image_message = [{"type": "image_url", "image_url": {"url": f"data:image/png;base64,{img_data}"}}]
messages.append({"role": "user", "content": image_message})
else:
messages.append({"role": "user", "content": message})
try:
response = client.chat.completions.create(
model=model_choice,
messages=messages,
max_tokens=max_tokens,
temperature=temperature,
top_p=top_p,
web_search=web_search
)
formatted_response = format_output(response.choices[0].message.content)
return formatted_response
except Exception as e:
print(f"エラー発生: {e}")
return "エラーが発生しました。再試行してください。"
def chat(message, history, system_message, max_tokens, temperature, top_p, model_choice, web_search, image):
if message.strip() == "" and not image:
return "", history, history
# 画像がアップロードされている場合、dataURLに変換
if image:
image_data_url = convert_image_to_dataurl(image)
else:
image_data_url = None
print("メッセージ送信直後の履歴:", history) # メッセージ送信直後に履歴を表示
response = respond(message, history, system_message, max_tokens, temperature, top_p, model_choice, web_search, image_data_url)
history = history + [(message, response)]
print("AIの回答後の履歴:", history) # AIの回答後に履歴を表示
# 入力欄をクリアして、更新済みのチャット履歴と状態を返す
return "", history, history
with gr.Blocks() as demo:
with gr.Row():
# 左側のカラム:入力欄と各オプションを配置
with gr.Column():
# オプション(システムメッセージや各種パラメータ)
system_message = gr.Textbox(
value="あなたは日本語しか話せません。あなたは最新の医療支援AIです。薬の紹介、薬の提案、薬の作成など、さまざまなタスクに答えます。また、新しい薬を開発する際は、既存のものに頼らずに画期的なアイデアを出します。",
label="システムメッセージ"
)
max_tokens = gr.Slider(minimum=1, maximum=2048, value=512, step=1, label="トークン制限")
temperature = gr.Slider(minimum=0.1, maximum=4.0, value=2, step=0.1, label="Temperature (数値が大きいほど様々な回答をします。)")
top_p = gr.Slider(minimum=0.1, maximum=1.0, value=0.95, step=0.05, label="Top-p (nucleus sampling) (数値が低いと回答候補が上位のみになります。)")
model_choice = gr.Radio(choices=["gpt-4o-mini", "gpt-4o", "o3-mini"], value="gpt-4o", label="モデル選択")
web_search = gr.Checkbox(value=True, label="WEB検索")
# チャット入力欄と送信ボタン
chatbot_input = gr.Textbox(show_label=False, placeholder="ここにメッセージを入力してください...", lines=2)
image_input = gr.Image(type="pil", label="画像をアップロード") # 画像アップロード
submit_btn = gr.Button("送信")
# 右側のカラム:チャットの履歴を表示
with gr.Column():
chat_history_display = gr.Chatbot(label="チャット履歴")
# 会話の状態(履歴)を保持する State コンポーネント
state = gr.State([])
# 送信ボタン押下時の挙動
submit_btn.click(
chat,
inputs=[chatbot_input, state, system_message, max_tokens, temperature, top_p, model_choice, web_search, image_input],
outputs=[chatbot_input, chat_history_display, state]
)
# エンターキーでの送信にも対応
chatbot_input.submit(
chat,
inputs=[chatbot_input, state, system_message, max_tokens, temperature, top_p, model_choice, web_search, image_input],
outputs=[chatbot_input, chat_history_display, state]
)
demo.launch()