import json import os import random import gradio as gr import openai import requests from langchain.callbacks.base import CallbackManager from langchain.callbacks.streaming_stdout import StreamingStdOutCallbackHandler from langchain.chains import ConversationChain from langchain.chat_models import ChatOpenAI from langchain.memory import ConversationBufferWindowMemory from langchain.prompts.chat import (ChatPromptTemplate, HumanMessagePromptTemplate, MessagesPlaceholder, SystemMessagePromptTemplate) from pydub import AudioSegment from pydub.playback import play # 会話チェーン conversation = None # APIキーの設定 #os.environ["OPENAI_API_KEY"] = "" openai.api_key = os.getenv('OPENAI_API_KEY') os.environ["OPENAI_API_KEY"] = openai.api_key # 検索APIURL search_url = 'https://greendb.shanri.co.jp/gd/search/' # 設定プロンプト character_setting = "あなたは20代の看護師さんです。明るい性格で丁寧な口調で回答してください" def get_search_result(kw): # getメソッドでsearch urlに対してGETリクエストを送る r = requests.get(search_url, params={'kw':kw}) # JSONレスポンスからkotoba_shoujouをすべて取得 kotoba_shoujou = [] for hit in r.json()['hits']: kotoba_shoujou.append(hit['_source']['kotoba_shoujou']) # kotoba_shoujou文字列配列を/で連結 kotoba_shoujou_str = '/'.join(kotoba_shoujou) return kotoba_shoujou_str def speechRecognitionModel(input, chatbot, shoujou, bui, when, how, status): global conversation if not conversation: # チャットプロンプトテンプレート prompt = ChatPromptTemplate.from_messages([ SystemMessagePromptTemplate.from_template(character_setting), MessagesPlaceholder(variable_name="history"), HumanMessagePromptTemplate.from_template("{input}") ]) # チャットモデル llm = ChatOpenAI( model_name="gpt-3.5-turbo", max_tokens=512, temperature=0.2, streaming=True, callback_manager=CallbackManager([StreamingStdOutCallbackHandler()]) ) # メモリ memory = ConversationBufferWindowMemory(k=3, return_messages=True) # 会話チェーン conversation = ConversationChain(memory=memory, prompt=prompt, llm=llm, verbose=False) os.rename(input, input + '.wav') file = open(input + '.wav', "rb") result = openai.Audio.transcribe(file=file, model="whisper-1", response_format="text", language="ja") message = f'以下に症状を示すテキストがあります。症状、いつから、どんな、つらい場所についてjson形式でまとめてください。\n{result}' response = conversation.predict(input=message) print(response) # 文字列を辞書に変換 dict_data = json.loads(response) # 辞書のキーで値にアクセス shoujou = dict_data["症状"] when = dict_data["いつから"] how = dict_data["どんな"] bui = dict_data["つらい場所"] message = f'以下に患者さんが症状について説明した文章があります。回答のお礼と症状、いつから、どんな、つらい場所などについてまとめてねぎらってください。\n{result}' response = conversation.predict(input=message) chatbot += [[result, response]] chatbot += [[None, '引き続き質問させていただきますね。']] if shoujou == '不明': status = START chatbot += [[None, '症状について教えてください。']] elif bui == '不明': chatbot += [[None, '体のどのあたり(部位)がつらいか詳しく教えてください。']] status = BUI elif when == '不明': chatbot += [[None, 'いつから症状が始まりましたか?経過を教えてください。']] status = WHEN elif how == '不明': chatbot += [[None, '他、どのくらい症状はお辛いですか?']] status = HOW else: chatbot += [[None, '他、いつもと違うなと思う症状や思い当たることはあったりしますか。']] status = RELEVANCE return chatbot, shoujou, bui, when, how, status def user(message, history): return "", history + [[message, None]] def chat(history, status, suggest, shoujou, bui, hosoku, when, how, relevance, kiou, fukuyaku, allergy, family, job, drink, smoke, sports, stress, etc, result): user_message = history[-1][0] if status == START: if shoujou == '不明': history[-1][1] = '症状について教えてください。' else: status += 1 if status == SYOUJOU: status +=1 shoujou = user_message history[-1][1] = '体のどのあたり(部位)がつらいか詳しく教えてください。' elif status == BUI: status += 1 bui = user_message history[-1][1] = '候補の中から症状に近い「症状ことば」があれば入力してください。\n特になければエンターを入力してください。' suggest = get_search_result(shoujou).split('/') suggest = random.sample(suggest, 20) suggest = ' '.join(suggest) elif status == HOSOKU: hosoku = user_message suggest = '症状ことばの候補が表示されます。' message = f'私は看護師です。私は、患者様に「今日はどんな症状でお困りですか?」と質問し、患者様は「{shoujou}」と答えました。さらに、私は「体のどのあたり(部位)がつらいか詳しく教えてください。」と質問し、患者様は「{bui}」と答えました。上記は症状に関わる回答ですか。はい、いいえで答えてください。' response = conversation.predict(input=message) history[-1][1] = response if 'はい' in response: status += 1 message = f'以下の文章をまとめ、確認してください。\n{shoujou}。{bui}。{hosoku}' response = conversation.predict(input=message) history[-1][1] = f'{response}\nこれから上手く症状をお伝えできるように色々質問します。\nいつから症状が始まりましたか?経過を教えてください。' else: history[-1][1] = f'{response}\nお力になれるよう、改めてもう少し詳しく症状をお伺いできますか?' elif status == WHEN: status += 1 when = user_message history[-1][1] = 'どのくらい症状はお辛いですか?' elif status == HOW: status += 1 how = user_message history[-1][1] = '他、いつもと違うなと思う症状や思い当たることはあったりしますか。' elif status == RELEVANCE: status += 1 relevance = user_message message = f'私は看護師です。以下をまとめ、まとめた文章だけを記載してください。\n{shoujou}。{bui}。{hosoku}。{when}。{how}。{relevance}。' response = conversation.predict(input=message) history[-1][1] = response + '\n今までかかった病気や現在治療中の病気はありますか?' elif status == KIOU: status += 1 kiou = user_message history[-1][1] = '現在飲まれているお薬やサプリメントはありますか?' elif status == FUKUYAKU: status += 1 fukuyaku = user_message history[-1][1] = '体質についてお伺いさせてください。\n・特になし\n・アレルギーあり\n・便秘しやすい\n・下痢しやすい\n・かぶれやすい\n・胃が弱い\n・冷え性\n・その他' elif status == ALLERGY: status += 1 allergy = user_message message = f'私は看護師です。以下をまとめ、まとめた文章だけを記載してください。{kiou}。{fukuyaku}, {allergy}。' response = conversation.predict(input=message) history[-1][1] = f'{response}\n医師はあなたをよく理解して治療をしたいと考えていますよ。\nあなたのライフスタイルを少しお伺いさせてください。\nご家族と一緒に住んでいますか?それとも一人暮らしですか?' elif status == FAMILY: status += 1 family = user_message message = f'私は看護師です。私は、患者様に「ご家族と一緒に住んでいますか?それとも一人暮らしですか?」と質問し、患者様は\n「{family}」と回答しました。これは質問に対する適切な回答ですか。はい、いいえで答えてください。' response = conversation.predict(input=message) if 'はい' in response: history[-1][1] = 'どんなお仕事をされていらっしゃいますか。' else: history[-1][1] = '次の質問へうつりますね。\nどんなお仕事をされていらっしゃいますか。' elif status == JOB: status += 1 job = user_message message = f'私は看護師です。私は、患者様に「どんなお仕事をされていらっしゃいますか。」と質問し、患者様は\n「{job}」と回答しました。これは質問に対する適切な回答ですか。はい、いいえで答えてください。' response = conversation.predict(input=message) if 'はい' in response: history[-1][1] = 'お酒を飲まれますか?\n・お酒は飲まない\n・お酒を飲む→(お酒の種類・量・頻度を教えてください。例:缶ビール2本を毎日)' else: history[-1][1] = '次の質問へうつりますね。\nお酒を飲まれますか?\n・お酒は飲まない\n・お酒を飲む→(お酒の種類・量・頻度を教えてください。例:缶ビール2本を毎日)' elif status == DRINK: status += 1 drink = user_message message = f'私は看護師です。私は、患者様に「お酒を飲まれますか?お酒の種類・量・頻度を教えてください。」と質問し、患者様は\n「{drink}」と回答しました。これは質問に対する適切な回答ですか。はい、いいえで答えてください。' response = conversation.predict(input=message) if 'はい' in response: history[-1][1] = 'タバコを吸われますか?\n・タバコは吸わない\n・タバコは以前吸っていたがやめた・タバコを吸う→(一日何本吸いますか?)' else: history[-1][1] = '次の質問へうつりますね。\nタバコを吸われますか?\n・タバコは吸わない\n・タバコは以前吸っていたがやめた・タバコを吸う→(一日何本吸いますか?)' elif status == SMOKE: status += 1 smoke = user_message message = f'私は看護師です。私は、患者様に「タバコを吸われますか?一日何本吸いますか?」と質問し、患者様は\n「{smoke}」と回答しました。これは質問に対する適切な回答ですか。はい、いいえで答えてください。' response = conversation.predict(input=message) if 'はい' in response: history[-1][1] = '運動はされますか?\n・運動はしない\n・運動をする→(どんな運動をされますか?頻度は?)' else: history[-1][1] = '次の質問へうつりますね。\n運動はされますか?\n・運動はしない\n・運動をする→(どんな運動をされますか?頻度は?)' elif status == SPORTS: status += 1 sports = user_message message = f'私は看護師です。私は、患者様に「運動はされますか?どんな運動をされますか?頻度は?」と質問し、患者様は\n「{sports}」と回答しました。これは質問に対する適切な回答ですか。はい、いいえで答えてください。' response = conversation.predict(input=message) if 'はい' in response: history[-1][1] = '夜は十分睡眠がとれていますか?\n・睡眠がとれている\n・睡眠がとれていない→(どんなことでお困りですか?)' else: history[-1][1] = '次の質問へうつりますね。\n夜は十分睡眠がとれていますか?\n・睡眠がとれている\n・睡眠がとれていない→(どんなことでお困りですか?)' elif status == STRESS: status += 1 stress = user_message message = f'私は看護師です。以下をまとめ、まとめた文章だけを記載してください。{family}、{job}、{drink}、{smoke}、{sports}、{stress}、{etc}。' response = conversation.predict(input=message) history[-1][1] = f'{response}\n最後に何か医師にお伝えされたいこと、お聞きになりたいことはありますか。' elif status == ETC: etc = user_message message = f'私は看護師です。以下をまとめ、箇条書きで記載してください。{shoujou}、{bui}、{hosoku}、{when}、{relevance}、{kiou}、{fukuyaku}、{allergy}、{family}、{job}、{drink}、{smoke}、{sports}、{stress}、{etc}。' history[-1][1] = conversation.predict(input=message) message = f'私は看護師です。以下をまとめ、箇条書きで記載してください。症状:{shoujou}、部位:{bui}、補足:{hosoku}、いつから:{when}、いつもと違う:{relevance}、既往症:{kiou}、服薬:{fukuyaku}、アレルギー:{allergy}、家族歴:{family}、職歴:{job}、飲酒:{drink}、喫煙:{smoke}、運動:{sports}、ストレス:{stress}、その他:{etc}。' result = conversation.predict(input=message) return history, status, suggest, shoujou, bui, hosoku, when, how, relevance, kiou, fukuyaku, allergy, family, job, drink, smoke, sports, stress, etc, result def init_firstmsg(): history = [[None, '医師に症状を伝えるときに役立つ初診問診をスタートしますね!']] history += [[None, '今日はどんな症状でお困りですか?']] history += [[None, 'いつから、どんな、どのくらいの症状があるでしょうか。また、つらい場所などもお伝え下さい。']] history += [[None, 'それでは録音ボタンを押してお話ください。終わりましたらもう一度録音ボタンを押してください。']] return history START = 0 SYOUJOU = 1 BUI = 2 HOSOKU = 3 WHEN = 4 HOW = 5 RELEVANCE = 6 KIOU = 7 FUKUYAKU = 8 ALLERGY = 9 FAMILY = 10 JOB = 11 DRINK = 12 SMOKE = 13 SPORTS = 14 STRESS = 15 ETC = 16 # フロントエンド with gr.Blocks() as demo: with gr.Column(scale=0.6): # コンポーネント firstmsg = gr.Chatbot() audio = gr.inputs.Audio(source="microphone", type="filepath") chatbot = gr.Chatbot() msg = gr.Textbox(show_label = False) gr.Markdown('---') suggest = gr.Textbox(label = '候補', interactive = False, value = '症状ことばの候補が表示されます。') status = gr.Number(value = START, visible = False) shoujou = gr.Textbox(visible = False) bui = gr.Textbox(visible = False) hosoku = gr.Textbox(visible = False) when = gr.Textbox(visible = False) how = gr.Textbox(visible = False) relevance = gr.Textbox(visible = False) kiou = gr.Textbox(visible = False) fukuyaku = gr.Textbox(visible = False) allergy = gr.Textbox(visible = False) family = gr.Textbox(visible = False) job = gr.Textbox(visible = False) drink = gr.Textbox(visible = False) smoke = gr.Textbox(visible = False) sports = gr.Textbox(visible = False) stress = gr.Textbox(visible = False) etc = gr.Textbox(visible = False) result = gr.Textbox(label = 'まとめ', interactive = False) demo.load(init_firstmsg, None, firstmsg, queue=False) audio.change(speechRecognitionModel, inputs=[audio, chatbot, shoujou, bui, when, how, status], outputs=[chatbot, shoujou, bui, when, how, status]) # audio.change(chat, [chatbot, status, suggest, shoujou, bui, hosoku, when, how, relevance, kiou, fukuyaku, allergy, family, job, drink, smoke, sports, stress, etc, result], [chatbot, status, suggest, shoujou, bui, hosoku, when, how, relevance, kiou, fukuyaku, allergy, family, job, drink, smoke, sports, stress, etc, result]) # demo.load(init_chatbot, None, chatbot, queue=False) msg.submit(user, [msg, chatbot], [msg, chatbot], queue=False).then( chat, [chatbot, status, suggest, shoujou, bui, hosoku, when, how, relevance, kiou, fukuyaku, allergy, family, job, drink, smoke, sports, stress, etc, result], [chatbot, status, suggest, shoujou, bui, hosoku, when, how, relevance, kiou, fukuyaku, allergy, family, job, drink, smoke, sports, stress, etc, result] ) if __name__ == "__main__": demo.launch()