import base64 import os import shutil import threading import time import gradio as gr from api import audio_text from blog_class import generate_item, knowledge_class, save_feedback from design import ( custom_css, custom_head, js_func, params_text, speaker_text, title_html, title_text, ) from prompts import TRANS_Prompt, TRANS_Prompt_template knowledge_cls = knowledge_class() language_dict = {"en": "English", "cn": "Chinese"} def update_knowledge(): knowledge_cls.get_new_knowledge() choices_list = list(knowledge_cls.reference_dict.keys()) return gr.update(choices=choices_list) def user_message_fn(user_message, history): if history is None: history = [] history.append({"role": "user", "content": user_message}) return "", history def answer_question( history, creative_flag, full_flag, audio_flag, speaker_flag, language_flag ): print("chat Start") answer_text, info_title, audio_file_path = knowledge_cls.get_chat_answer( history, creative_flag, full_flag, speaker_flag ) if not answer_text: yield history return if language_flag not in ["jp"]: info_title = info_title + f"日本語返信:\n {answer_text}\n" sys_prompt = TRANS_Prompt.format(lang=language_dict[language_flag]) user_prompt = TRANS_Prompt_template.format( japanese_text=answer_text, lang=language_dict[language_flag] ) answer_text = generate_item(user_prompt, sys_prompt) # text history.append({"role": "assistant", "content": ""}) # audio history.append( { "role": "assistant", "content": "音声なし", "metadata": {"title": "🎧 音声返信", "status": "done"}, } ) # ref history.append( { "role": "assistant", "content": info_title, "metadata": {"title": "📚 参照ナレッジ", "status": "done"}, } ) def run_audio_answer(): run_audio_path = audio_text(answer_text, audio_file_path, speaker_flag) audio_str = base64.b64encode(open(run_audio_path, "rb").read()).decode("utf-8") history[-2]["content"] = gr.HTML( f""" """ ) history[-2]["metadata"] = {"title": "🎧 音声返信", "status": "done"} if not audio_flag: audio_thread = threading.Thread(target=run_audio_answer) audio_thread.start() history[-2]["content"] = "音声作成中..." history[-2]["metadata"]["status"] = "pending" # for char in answer_text: history[-3]["content"] += char yield history time.sleep(0.03) if not audio_flag: while audio_thread.is_alive(): yield history time.sleep(0.2) yield history def handle_feedback(like_data: gr.LikeData): save_feedback(like_data.value[0], like_data.liked) def get_reference_info(selected_reference): reference_dict = knowledge_cls.reference_dict.get(selected_reference, None) if reference_dict: yield ( reference_dict["audio"], reference_dict["original_text"], reference_dict["summary"], ) else: yield (None, None, None) def zip_directory(): zip_path = "resource.zip" if os.path.exists(zip_path): os.remove(zip_path) shutil.make_archive(zip_path.replace(".zip", ""), "zip", "./resource") return zip_path def toggle_change(): return None, None with gr.Blocks(title="勉強会", css=custom_css, head=custom_head, js=js_func) as demo: with gr.Sidebar(label="回答スタイル調整", open=False): with gr.Accordion("回答スタイルの違いについて", open=False): gr.Markdown(params_text) creativity_toggle = gr.Radio( [("創造的な回答", True), ("事実的な回答", False)], value=False, label="回答スタイル", ) length_toggle = gr.Radio( [("詳細な説明", True), ("簡潔な説明", False)], value=False, label="説明スタイル", ) audio_toggle = gr.Radio( [("テキスト", True), ("音声とテキスト", False)], value=False, label="返信スタイル", ) language_toggle = gr.Radio( [("日本語", "jp"), ("中文", "cn"), ("English", "en")], value="jp", label="言語スタイル", ) with gr.Accordion("話者紹介", open=False): gr.Markdown(speaker_text) speaker_toggle = gr.Radio( [ ("さらとが", "matsu"), ("ケンシロウ", "ken"), ("まな", "mana"), ("藤井", "ren"), ("内山", "cai"), ], value="matsu", label="話者スタイル", ) # creativity_toggle = Toggle( # label="創意内容", # value=False, # interactive=True, # color="#007bff", # ) # length_toggle = Toggle( # label="詳細内容", # value=False, # interactive=True, # color="#007bff", # ) with gr.Column(elem_id="title-area"): gr.HTML(title_html) gr.HTML(title_text) with gr.Column(elem_id="chatbot-container"): gr.HTML( "

何かお困りですか?

", ) chatbot = gr.Chatbot( show_label=False, type="messages", bubble_full_width=False, avatar_images=( None, "https://cdn.profile-image.st-hatena.com/users/saratoga623/profile.png?1728512391", ), ) with gr.Row(elem_id="submit-btn"): msg = gr.Textbox( placeholder="質問を入力してEnter...", show_label=False, scale=5, container=False, ) submit_btn = gr.Button(value="送信 🚀", scale=1) clear_btn = gr.ClearButton([msg, chatbot], value="クリア 🧹", scale=1) with gr.Accordion("ナレッジ一覧", elem_id="references-container", open=False): with gr.Column(): with gr.Row(): gr.HTML("

ナレッジ一覧

") update_btn = gr.Button(value="🔄 更新", elem_id="update-btn") references_dropdown = gr.Dropdown( label="ナレッジを選ぶ", choices=list(knowledge_cls.reference_dict.keys()), value=None, ) reference_audio = gr.Audio( label="ナレッジ要約を聞く", type="filepath", interactive=False, waveform_options=gr.WaveformOptions( show_recording_waveform=False, show_controls=False, ), ) sum_references_box = gr.Textbox( label="ナレッジ要約", lines=4, interactive=False, ) with gr.Accordion("ナレッジ详情", open=False): all_references_box = gr.Markdown(max_height=250) with gr.Accordion("資源", open=False, elem_id="download-container"): download_btn = gr.Button("ダウンロード", elem_id="update-btn") file_output = gr.File(show_label=False, container=False) msg.submit( fn=user_message_fn, inputs=[msg, chatbot], outputs=[msg, chatbot], queue=False ).then( fn=answer_question, inputs=[ chatbot, creativity_toggle, length_toggle, audio_toggle, speaker_toggle, language_toggle, ], outputs=chatbot, ) submit_btn.click( fn=user_message_fn, inputs=[msg, chatbot], outputs=[msg, chatbot], queue=False ).then( fn=answer_question, inputs=[ chatbot, creativity_toggle, length_toggle, audio_toggle, speaker_toggle, language_toggle, ], outputs=chatbot, ) chatbot.like(handle_feedback, None, None, like_user_message=True) update_btn.click( fn=update_knowledge, outputs=references_dropdown, ) references_dropdown.change( fn=get_reference_info, inputs=references_dropdown, outputs=[reference_audio, all_references_box, sum_references_box], ) download_btn.click(fn=zip_directory, outputs=file_output) creativity_toggle.change(fn=toggle_change, inputs=None, outputs=[msg, chatbot]) length_toggle.change(fn=toggle_change, inputs=None, outputs=[msg, chatbot]) audio_toggle.change(fn=toggle_change, inputs=None, outputs=[msg, chatbot]) language_toggle.change(fn=toggle_change, inputs=None, outputs=[msg, chatbot]) speaker_toggle.change(fn=toggle_change, inputs=None, outputs=[msg, chatbot]) # app if __name__ == "__main__": demo.launch(inline=False, share=False, debug=True)