|
import gradio_client.utils |
|
|
|
orig__json_schema_to_python_type = gradio_client.utils._json_schema_to_python_type |
|
def safe__json_schema_to_python_type(schema, defs=None): |
|
if schema is True: |
|
return "any" |
|
if schema is False: |
|
return "none" |
|
return orig__json_schema_to_python_type(schema, defs) |
|
gradio_client.utils._json_schema_to_python_type = safe__json_schema_to_python_type |
|
|
|
orig_get_type = gradio_client.utils.get_type |
|
def safe_get_type(schema): |
|
if not isinstance(schema, dict): |
|
return "any" |
|
return orig_get_type(schema) |
|
gradio_client.utils.get_type = safe_get_type |
|
|
|
import os |
|
import gradio as gr |
|
from datetime import datetime |
|
import pytz |
|
|
|
try: |
|
from groq import Groq |
|
from notion_client import Client |
|
except ImportError: |
|
os.system('pip install groq notion-client pytz') |
|
from groq import Groq |
|
from notion_client import Client |
|
|
|
|
|
groq_client = Groq(api_key=os.getenv('groq_key')) |
|
notion_client = Client(auth=os.getenv('NOTION_API_KEY')) |
|
NOTION_DB_ID = os.getenv('NOTION_DB_ID') |
|
|
|
def log_to_notion(name, user_input, bot_response): |
|
try: |
|
taiwan_tz = pytz.timezone('Asia/Taipei') |
|
timestamp = datetime.now(taiwan_tz).strftime("%Y-%m-%d %H:%M:%S") |
|
notion_client.pages.create( |
|
parent={"database_id": NOTION_DB_ID}, |
|
properties={ |
|
"Name": { |
|
"title": [{"text": {"content": name or "匿名用戶"}}] |
|
}, |
|
"Timestamp": { |
|
"date": {"start": timestamp} |
|
}, |
|
"User Input": { |
|
"rich_text": [{"text": {"content": user_input}}] |
|
}, |
|
"Bot Response": { |
|
"rich_text": [{"text": {"content": bot_response}}] |
|
} |
|
} |
|
) |
|
except Exception as e: |
|
print(f"Error logging to Notion: {e}") |
|
|
|
def get_system_prompt(selected_option): |
|
if selected_option == "佛法": |
|
return ( |
|
"你是一位智慧圓滿、慈悲充滿的佛教老師,與人對話時常用佛法、禪學與東方哲理為基礎。" |
|
"每次回答請主動引用佛教經典(例如金剛經/心經/法句經/阿含經等)的原文、偈語、公案或譬喻,並標明出處," |
|
"用溫和、同理心、啟發式的語氣講解經文含義及其如何照亮對方當下的困惑。" |
|
"善於傾聽並以正見引導對方發現智慧與平靜,遇到負面議題積極導回慈悲與希望與正念。" |
|
"所有回答都用標準流暢的繁體中文,避免錯別字及中英夾雜。首次回應簡潔,持續追問可再深入。" |
|
) |
|
elif selected_option == "聖經-和合本": |
|
return ( |
|
"你是一位身在人間的天使,專精聖經和合本。" |
|
"每次回答請主動引用聖經和合本與問題相關的經文,明確標出書名、章、節(例如:馬太福音5:14)," |
|
"並以溫暖正向的語氣解釋經文含義、故事背景,以及這段經文如何啟發提問者正向面對困境。" |
|
"務必讓經文成為解答的依據和力量來源。所有回答都要用正確繁體中文,若引用其他語言請主動翻譯。" |
|
"首次回覆簡短、重點明確,遇到負向提問積極導回正向。" |
|
) |
|
elif selected_option == "聖經-恢復本": |
|
return ( |
|
"你是一位天使,專業於聖經恢復本(Recovery Version)。" |
|
"回答時請主動引用恢復本裡與問題相關的經節,標明書名、章節(例如:約翰福音3:16)," |
|
"以溫柔細膩、正向、同理心的語氣解釋經文意境、屬靈啟示與與當下問題的聯繫。" |
|
"請著重恢復本的註解與信息,務求讓提問者透過經文獲得慰藉、希望與力量。" |
|
"一律用正確繁體中文回答,有引用外文請主動翻譯。首次簡明回應,追問可加強。" |
|
) |
|
elif selected_option == "一貫道": |
|
return ( |
|
"你是一位祥和、博學的道師,精通一貫道融合三教(儒、釋、道)義理。" |
|
"請在回答時主動引用《中庸》《大學》《論語》《道德經》《金剛經》或一貫道訓典、經典格言(並說明來源)," |
|
"解釋原文與當前提問的關聯,結合生活指導、修身養性之法協助對方。" |
|
"語氣誠懇、啟發且正面,強調孝道、誠信、善行。回應務必全程用正確繁體中文。首次回答簡明重點,追問可詳述。" |
|
) |
|
elif selected_option == "無神論": |
|
return ( |
|
"你是一位理性、開明且富同理心的現代思想導師,以科學、邏輯與哲學思維協助對方解析人生。" |
|
"請每次回答主動引用著名科學家、哲學家(如愛因斯坦、卡繆、史蒂芬·霍金、羅素等)的名言或重要論點,並註明出處," |
|
"同時用淺白語言解釋這些理念怎麼啟發提問者面對現實。" |
|
"鼓勵思辨、自信、實證,並溫和引導對方正面積極看待問題。所有回答均使用正確、清晰繁體中文。" |
|
) |
|
elif selected_option == "玄學": |
|
return ( |
|
"你是一位豁達又神秘的東方玄學大師,精通易經、命理、風水、五行和占星等傳統術數。" |
|
"回答時請主動引用易經卦辭、命理詩句、占星經典句、風水訓示,並標明出處或派別," |
|
"用啟發、鼓勵且富人生哲理的方式,說明這些典籍智慧如何助對方突破迷惘、發現新契機。" |
|
"請全程以正確繁體中文作答,無中英混雜或錯字。初答簡要,後續可深入展開。" |
|
) |
|
else: |
|
return ( |
|
"你是一位功力高強且德高望眾的通靈老師,善於用經典智慧協助發問者從不同信仰與學說找到人生啟示,並給予正向的力量。" |
|
"回答主動引用各學派經典句子或案例做依據,並用繁體中文說明。" |
|
) |
|
|
|
def chatbot_response(name, message, chat_history, selected_option): |
|
name = name.strip() if name else "匿名用戶" |
|
system_prompt = { |
|
"role": "system", |
|
"content": get_system_prompt(selected_option) |
|
} |
|
messages = [system_prompt] |
|
for human, assistant in chat_history or []: |
|
messages.append({"role": "user", "content": human}) |
|
messages.append({"role": "assistant", "content": assistant}) |
|
messages.append({"role": "user", "content": message}) |
|
|
|
try: |
|
completion = groq_client.chat.completions.create( |
|
model="meta-llama/llama-4-maverick-17b-128e-instruct", |
|
messages=messages, |
|
temperature=0.8, |
|
max_tokens=2048, |
|
top_p=0.95, |
|
stream=False |
|
) |
|
bot_response = completion.choices[0].message.content |
|
log_to_notion(name, message, bot_response) |
|
return bot_response |
|
except Exception as e: |
|
print(f"Groq API 調用錯誤: {e}") |
|
return "很抱歉,我遇到了一些技術問題。請稍後再試。" |
|
|
|
with gr.Blocks(css=""" |
|
.gradio-container {background: linear-gradient(to right, #ffecd2, #fcb69f);} |
|
.gr-textbox {background-color: #080808; color: #f8f8ff;} |
|
.gr-button {background-color: #080808; color: #f8f8ff; height: 100%;} |
|
.gr-radio {background-color: #080808; color: #f8f8ff;} |
|
.gr-markdown h2, .gr-markdown p {color: #f8f8ff;} |
|
""") as demo: |
|
name_input = gr.Textbox(label="您的姓名", placeholder="請輸入您的名字或暱稱", elem_classes="gr-textbox") |
|
options = gr.Radio( |
|
choices=["佛法", "聖經-和合本", "聖經-恢復本", "一貫道", "無神論", "玄學"], |
|
label="選擇您的信仰", |
|
value="佛法", |
|
elem_classes="gr-radio" |
|
) |
|
chatbot = gr.Chatbot(label="聖者與您對話,歡迎詢問生命的奧秘和智慧,算命也可以喔!", height=450, value=[]) |
|
with gr.Row(): |
|
msg_input = gr.Textbox(label="您的訊息", placeholder="在此輸入您想詢問的問題", scale=8, elem_classes="gr-textbox") |
|
submit_btn = gr.Button("送出", scale=1, elem_classes="gr-button") |
|
clear_btn = gr.Button("清除對話", elem_classes="gr-button") |
|
|
|
def submit_message(name, message, chat_history, selected_option): |
|
chat_history = chat_history or [] |
|
response = chatbot_response(name, message, chat_history, selected_option) |
|
chat_history.append((message, response)) |
|
return "", chat_history |
|
|
|
def clear_chat(): |
|
return [] |
|
|
|
msg_input.submit( |
|
submit_message, |
|
[name_input, msg_input, chatbot, options], |
|
[msg_input, chatbot] |
|
) |
|
submit_btn.click( |
|
submit_message, |
|
[name_input, msg_input, chatbot, options], |
|
[msg_input, chatbot] |
|
) |
|
clear_btn.click(clear_chat, None, chatbot) |
|
gr.Markdown("## 仁者見仁,智者見智") |
|
|
|
if __name__ == "__main__": |
|
demo.launch() |