FAQ-workshop / app.py
yeelou's picture
add cai ren speaker
05d04ce
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"""
<audio controls>
<source src="data:audio/mp3;base64,{audio_str}" type="audio/mp3">
</audio>
"""
)
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(
"<h3><i class='fa fa-question-circle'></i> 何かお困りですか?</h3>",
)
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("<h3><i class='fa fa-book'></i> ナレッジ一覧</h3>")
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)